dbt

dbt_expectationsでデータ品質を向上させよう

はじめに

こんにちは、中村です。
皆さんはdbt(data build tool)を使ってデータ変換や管理を行う中で、dbt testの機能に少し物足りなさを感じたことはありませんか?

dbtはシンプルかつ強力なデータ変換ツールとして非常に便利ですが、標準のdbt testコマンドで実施できるテストには限界があります。

そこで今回は、dbtの標準機能を補完し、より高度なテストを可能にする拡張パッケージの活用方法について紹介します。

目次

【前提】dbt testでできるテスト

まずは、そもそもdbt testって何ができたのかを確認しましょう!

dbt testにはsingular testとgeneric testの2種類があり、singular testは結果が0件になることを期待するSQLを書き、あってほしくない結果がないか検証するテストです。

例えば、注文日に今日より未来の日付が入っていたら問題ですよね。そのような場合には以下のSQLでテストができます。

#tests/*.sql
SELECT *
FROM {{ ref('orders') }}
WHERE order_date > CURRENT_DATE

一方、generic testにはデフォルトで以下の4種類のテストがあります。

  • not_null: nullが含まれていないか
  • unique: 値が全てuniqueか
  • accepted_values:指定した値以外が入っていないか
  • relationships: あるカラムに元テーブルのカラムに存在しない値が入っていないか

またcustom generic testがあり、こちらもSQLを記述してテストを作成できます。

こちらはsingular testと異なり、使いまわせるのが利点です。例えば、注文日に限らず日付のカラムで未来の日付が入ってほしくないときは、以下のSQLでテストができます。

#macros/*.sql
{% test assert_not_in_future(model, column_name) %}

    SELECT *
    FROM {{ model }}
    WHERE {{ column_name }} > CURRENT_DATE

{% endtest %}

しかし大量のモデルがあり、それぞれに課したい制約が異なるとき、デフォルトのgeneric testではテスト項目が足りず、singular testやcustom generic testでは記述に手間がかかるという問題があります。そこでdbt_expectationsの出番です。

dbt_expectationsとは

dbt_expectationsは、dbt(data build tool)の拡張パッケージであり、PythonのGreat Expectationsパッケージに着想を得て作られました。検証項目の分類は7種類あり、テスト項目は全部で62項目もあります。(dbt testと被る項目があります。)

テスト項目の分類

  • テーブルの形状 (Table shape)
    列や行の数、構成、最近のデータ存在確認など、テーブルの外形的品質チェックを行う検証項目群
    • expect_column_to_exist
      指定したカラムが存在することを検証
    • expect_row_values_to_have_recent_data
      指定したカラムに、最新の日付(または時刻)データが含まれているかをチェック
    • expect_grouped_row_values_to_have_recent_data
      グループ単位(例:customer_idごと)で最新のデータがあるかを検証
    • expect_table_aggregation_to_equal_other_table
      集計値(sum, count など)が別のテーブルと一致するかを確認
    • expect_table_column_count_to_be_between
      カラム数が指定された範囲内であるかをチェック
    • expect_table_column_count_to_equal_other_table
      カラム数が別テーブルと一致していることを確認
    • expect_table_columns_count_to_equal
      正確なカラム数であることを検証する
    • expect_table_columns_to_not_contain_set
      指定したカラムがテーブルに含まれていないことを確認
    • expect_table_columns_to_contain_set
      指定したカラムがすべて存在することを確認
    • expect_table_columns_to_match_ordered_list
      指定された順序でカラムが並んでいることを検証
    • expect_table_columns_to_match_set
      指定したカラムの集合と完全一致していることを確認(順序は問わない)
    • expect_table_row_count_to_be_between
      テーブルの行数が指定された範囲内にあることを検証する
    • expect_table_row_count_to_equal_other_table
      別テーブルと行数が一致しているかを確認
    • expect_table_row_count_to_equal_other_table_times_factor
      別テーブルの行数に係数を掛けた数と一致するかをチェック
    • expect_table_row_count_to_equal
      正確に指定した件数であることを確認
  • 欠損値、一意な値、およびデータ型 (Missing values, unique values, and types)
    カラムの欠損・一意性・型の整合性を検証するための検証項目群
    • expect_column_values_to_be_null
      カラムの値がNULLであることを検証
    • expect_column_values_to_not_be_null
      カラムにNULLが含まれていないことを確認
    • expect_column_values_to_be_unique
      各カラムの値が一意であることを検証
    • expect_column_values_to_be_of_type
      カラムが指定されたデータ型であることを検証
    • expect_column_values_to_be_in_type_list
      指定された複数の型のいずれかに該当するかを検証
    • expect_column_values_to_have_consistent_casing
      文字列カラムの大文字小文字の一貫性をチェック
  • セットと範囲 (Sets and ranges)
    値の集合・範囲・傾向(増減)に関する検証項目群
    • expect_column_values_to_be_in_set
      各カラムの値が指定されたセット内にあることを検証
    • expect_column_values_to_not_be_in_set
      カラムの値が指定した値の集合に含まれていないことを検証
    • expect_column_values_to_be_between
      各カラムの値が2つの値の間にあることを検証
    • expect_column_values_to_be_decreasing
      カラムの値が降順になっているかを確認
    • expect_column_values_to_be_increasing
      カラムの値が昇順になっているかを確認
  • 文字列マッチング (String matching)
    長さ・パターンマッチ(LIKE / 正規表現)を通して、データの形式的な整合性を確認する検証項目群
    • expect_column_value_lengths_to_be_between
      文字列の長さが指定された範囲内にあることを確認
    • expect_column_value_lengths_to_equal
      文字列の長さが指定した長さと正確に一致することを確認
    • expect_column_values_to_match_like_pattern
      SQL の LIKE パターン(例:abc%)に一致することを確認
    • expect_column_values_to_match_like_pattern_list
      複数のLIKEパターンのいずれかに一致することを確認
    • expect_column_values_to_match_regex
      1つの正規表現パターンに一致することを確認
    • expect_column_values_to_match_regex_list
      複数の正規表現パターンのいずれかに一致することを確認
    • expect_column_values_to_not_match_like_pattern
      指定したLIKEパターンに一致しないことを検証する
    • expect_column_values_to_not_match_like_pattern_list
      指定された複数の LIKE パターンに一致しないことを確認
    • expect_column_values_to_not_match_regex
      指定した正規表現に一致しないことを検証
    • expect_column_values_to_not_match_regex_list
      複数の正規表現パターンのいずれにも一致しないことを確認
  • 集計関数 (Aggregate functions)
    列単位の集計結果を基にデータ品質を検証する検証項目群
    • expect_column_distinct_count_to_be_greater_than
      ユニークな値の数が指定した値より大きいことを検証
    • expect_column_distinct_count_to_be_less_than
      ユニークな値の数が指定した値より小さいことを検証
    • expect_column_distinct_count_to_equal_other_table
      他のテーブルの同じ列とユニーク値数が等しいことを検証
    • expect_column_distinct_count_to_equal
      ユニーク値数がぴったり指定値と等しいことを検証
    • expect_column_distinct_values_to_be_in_set
      ユニークな値のすべてが指定セットに含まれているかを検証
    • expect_column_distinct_values_to_contain_set
      指定した値のセットが列のユニーク値の中にすべて含まれていることを検証
    • expect_column_distinct_values_to_equal_set
      ユニーク値が指定セットと完全に一致することを検証
    • expect_column_max_to_be_between
      列の最大値が指定された範囲内にあるかを検証
    • expect_column_mean_to_be_between
      列の平均値が指定された範囲にあるかを検証
    • expect_column_median_to_be_between
      列の中央値が範囲内かを検証
    • expect_column_min_to_be_between
      列の最小値が指定された範囲にあるかを検証
    • expect_column_most_common_value_to_be_in_set
      最頻値(mode)が指定された集合の中にあるかを検証
    • expect_column_proportion_of_unique_values_to_be_between
      ユニーク値の割合(ユニーク数 ÷ 総行数)が指定された範囲内かを検証
    • expect_column_quantile_values_to_be_between
      任意の分位点の値が範囲内かを検証
    • expect_column_stdev_to_be_between
      標準偏差が範囲内かを検証
    • expect_column_sum_to_be_between
      列の合計値が範囲内かを検証
    • expect_column_unique_value_count_to_be_between
      ユニーク値の数が指定した範囲にあるかを検証(distinct_count と同義)
  • 複数カラム (Multi-column)
    複数列を同時に評価し整合性を検証する検証項目群
    • expect_column_pair_values_A_to_be_greater_than_B
      列 A の値が列 B より常に大きいことを検証
    • expect_column_pair_values_to_be_equal
      2列の値が同じであることを検証
    • expect_column_pair_values_to_be_in_set
      2列のペア(タプル)が指定された組み合わせセットに含まれているかを検証
    • expect_compound_columns_to_be_unique
      指定した複数列の組み合わせが一意(ユニーク)であることを検証
    • expect_multicolumn_sum_to_equal
      指定した複数列の合計値が別の列と一致することを検証
    • expect_select_column_values_to_be_unique_within_record
      1レコード内で指定列群の値がすべて異なることを検証
  • 分布関数 (Distributional functions)
    標準偏差や時系列パターンに基づき、データの異常値や欠損パターンをチェックするための検証項目群
    • expect_column_values_to_be_within_n_moving_stdevs
      移動平均と移動標準偏差に基づいて、列の値が過去の傾向(N標準偏差以内)に収まっているかを検証
    • expect_column_values_to_be_within_n_stdevs
      カラムの値が平均からn標準偏差以内であることを検証
    • expect_row_values_to_have_data_for_every_n_datepart
      指定の「期間単位(datepart)」で欠損なくデータがあるかを検証。例:毎日、毎週、毎月に少なくとも1件のデータがあるかを検証

dbt_expectationsを使ってみた

事前準備

まずpackages.ymlに以下を追加

packages:
  - package: metaplane/dbt_expectations
    version: 0.10.8 # バージョンは適宜変更してください

次にdbt depsを実行してください

dbt deps

最後にdbt_project.ymlでタイムゾーンを設定

vars:
  dbt_date_time_zone: 'Asia/Tokyo'

実行

今回は架空の製造業の製造ログデータを用いて検証項目を実際に使っていきます。
製品のマスターと製造ログをJOINしつつ、データの品質チェックをします。

今回使用するdbt-expectationsの検証項目は以下の3つです。これらをデフォルトのgeneric testと組み合わせて使ってみます。

  • expect_column_pair_values_A_to_be_greater_than_B
  • dbt_expectations.expect_column_sum_to_be_between
  • expect_column_values_to_match_regex
#ファイル構成
dbt_project/
├── models/
│   ├── staging/
│   │   ├── stg_production_logs.sql
│   │   ├── stg_production_logs.yml
│   │   ├── stg_product_master.sql
│   │   ├── stg_product_master.yml
│   ├── marts/
│   │   ├── production_logs.sql
├── seeds/
│   ├── seed_production_logs.csv
│   ├── seed_product_master.csv

各ファイルの中身は以下の通りです。

stg_product_master.sql
SELECT *
FROM {{ ref('seed_product_master') }}
stg_product_master.yml
version: 2

models:
  - name: stg_product_master
    description: "プロダクトマスターのステージングテーブル"
    columns:
      - name: product_id
        description: "製品ID(主キー)"
        tests:
          - not_null
          - unique
          - dbt_expectations.expect_column_values_to_match_regex:
              regex: '^P[0-9]{3}$'

      - name: product_name
        description: "製品名"
        tests:
          - not_null
stg_production_logs.sql
SELECT *
FROM {{ ref('seed_production_logs') }}
stg_production_logs.yml
version: 2

models:
  - name: stg_production_logs
    description: "製造業のログテーブル"
    tests:
      - dbt_expectations.expect_column_pair_values_A_to_be_greater_than_B:
          column_A: end_time
          column_B: start_time
          or_equal: True

    columns:
      - name: log_id
        description: "ログの一意な識別子"
        tests:
          - not_null
          - unique
          - dbt_expectations.expect_column_values_to_match_regex:
              regex: '^[0-9]{4}$'

      - name: line_id
        description: "生産ライン識別子"
        tests:
          - not_null
          - dbt_expectations.expect_column_values_to_match_regex:
              regex: '^LINE_[A-D]$'

      - name: product_id
        description: "製品識別子"
        tests:
          - not_null
          - dbt_expectations.expect_column_values_to_match_regex:
              regex: '^P[0-9]{3}$'

      - name: operator_id
        description: "オペレーター識別子"
        tests:
          - not_null
          - dbt_expectations.expect_column_values_to_match_regex:
              regex: '^OP[0-9]{2}$'

      - name: temperature
        description: "処理時の温度(度)"
        tests:
          - not_null
          - dbt_expectations.expect_column_sum_to_be_between:
              min_value: 60
              max_value: 100

      - name: start_time
        description: "処理開始日時"
        tests:
          - not_null

      - name: end_time
        description: "処理終了日時"
        tests:
          - not_null

      - name: status
        description: "処理状態(OK, FAILなど)"
        tests:
          - not_null
          - accepted_values:
              values: ['OK', 'FAIL']

      - name: part1_qty
        description: "部品1の個数"

      - name: part2_qty
        description: "部品2の個数"

      - name: total_parts
        description: "部品合計個数"
production_logs.sql
SELECT *
FROM {{ ref('stg_production_logs') }}
LEFT JOIN {{ ref('stg_product_master') }}
USING(product_id)
seeds/seed_product_master.csv
product_id,product_name
P001,Product_1
P002,Product_2
P003,Product_3
P004,Product_4
P005,Product_5
P006,Product_6
P007,Product_7
P008,Product_8
P009,Product_9
P010,Product_10
seeds/seed_production_logs.csv
log_id,line_id,product_id,operator_id,temperature,start_time,end_time,status,part1_qty,part2_qty,total_parts
1001,LINE_B,P003,OP01,77.48,2024-04-02 14:24:00,2024-04-02 14:35:00,OK,3,2,5
1002,LINE_A,P004,OP02,74.31,2024-04-08 01:14:00,2024-04-08 01:51:00,OK,1,1,2
1003,LINE_B,P008,OP05,78.24,2024-04-07 17:15:00,2024-04-07 17:37:00,FAIL,5,4,9
1004,LINE_C,P005,OP02,82.62,2024-04-01 09:46:00,2024-04-01 10:44:00,OK,2,4,6
1005,LINE_A,P006,OP03,73.83,2024-04-05 03:54:00,2024-04-05 04:10:00,FAIL,1,4,5
1006,LINE_A,P007,OP01,73.83,2024-04-01 19:51:00,2024-04-01 20:47:00,FAIL,4,5,9
1007,LINE_A,P004,OP03,82.9,2024-04-05 10:45:00,2024-04-05 11:31:00,OK,2,1,3
1008,LINE_D,P006,OP02,78.84,2024-04-03 23:34:00,2024-04-03 23:50:00,FAIL,4,3,7
1009,LINE_B,P009,OP02,72.65,2024-04-05 09:00:00,2024-04-05 09:23:00,OK,3,1,4
1010,LINE_B,P006,OP01,77.71,2024-04-06 14:13:00,2024-04-06 14:47:00,OK,3,5,8
1011,LINE_A,P004,OP05,72.68,2024-04-01 16:45:00,2024-04-01 17:15:00,FAIL,4,3,7
1012,LINE_D,P003,OP03,72.67,2024-04-03 18:03:00,2024-04-03 18:54:00,OK,4,4,8
1013,LINE_C,P010,OP04,76.21,2024-04-04 03:20:00,2024-04-04 04:17:00,FAIL,5,5,10
1014,LINE_D,P002,OP01,65.43,2024-04-05 10:50:00,2024-04-05 11:14:00,OK,2,5,7
1015,LINE_A,P007,OP04,66.38,2024-04-03 01:44:00,2024-04-03 02:34:00,FAIL,2,4,6
1016,LINE_A,P009,OP03,72.19,2024-04-07 08:29:00,2024-04-07 08:55:00,FAIL,5,1,6
1017,LINE_D,P001,OP03,69.94,2024-04-02 14:27:00,2024-04-02 14:55:00,OK,4,2,6
1018,LINE_B,P003,OP03,76.57,2024-04-07 02:37:00,2024-04-07 02:53:00,OK,3,5,8
1019,LINE_C,P008,OP01,70.46,2024-04-07 11:17:00,2024-04-07 12:16:00,OK,5,1,6
1020,LINE_B,P010,OP01,67.94,2024-04-05 11:07:00,2024-04-05 11:36:00,OK,2,1,3
1021,LINE_B,P008,OP05,82.33,2024-04-06 20:42:00,2024-04-06 20:56:00,OK,5,2,7
1022,LINE_B,P009,OP02,73.87,2024-04-04 08:22:00,2024-04-04 09:05:00,FAIL,5,4,9
1023,LINE_D,P002,OP02,75.34,2024-04-05 20:57:00,2024-04-05 21:49:00,OK,3,4,7
1024,LINE_B,P010,OP02,67.88,2024-04-02 01:29:00,2024-04-02 02:00:00,OK,1,5,6
1025,LINE_A,P001,OP03,72.28,2024-04-02 03:23:00,2024-04-02 04:18:00,OK,1,2,3
1026,LINE_B,P009,OP02,75.55,2024-04-07 04:23:00,2024-04-07 04:48:00,FAIL,3,4,7
1027,LINE_B,P002,OP01,69.25,2024-04-04 02:21:00,2024-04-04 03:21:00,FAIL,4,4,8
1028,LINE_A,P002,OP01,76.88,2024-04-05 08:44:00,2024-04-05 09:21:00,FAIL,4,4,8
1029,LINE_B,P009,OP04,72.0,2024-04-05 04:39:00,2024-04-05 04:55:00,OK,2,2,4
1030,LINE_B,P002,OP04,73.54,2024-04-06 03:12:00,2024-04-06 03:33:00,OK,3,4,7
1031,LINE_A,P004,OP02,71.99,2024-04-01 21:48:00,2024-04-01 22:39:00,FAIL,5,1,6
1032,LINE_A,P003,OP04,84.26,2024-04-06 20:36:00,2024-04-06 21:16:00,OK,2,4,6
1033,LINE_D,P009,OP04,74.93,2024-04-05 18:36:00,2024-04-05 19:02:00,OK,4,3,7
1034,LINE_A,P006,OP01,69.71,2024-04-03 11:51:00,2024-04-03 12:19:00,OK,2,1,3
1035,LINE_B,P001,OP05,79.11,2024-04-07 23:31:00,2024-04-08 00:11:00,OK,5,5,10
1036,LINE_B,P007,OP01,68.9,2024-04-03 10:44:00,2024-04-03 10:58:00,OK,5,1,6
1037,LINE_A,P007,OP05,76.04,2024-04-07 22:05:00,2024-04-07 22:53:00,FAIL,1,5,6
1038,LINE_C,P007,OP02,65.2,2024-04-04 07:12:00,2024-04-04 07:35:00,FAIL,3,2,5
1039,LINE_D,P010,OP05,68.36,2024-04-06 12:51:00,2024-04-06 13:21:00,OK,1,1,2
1040,LINE_C,P003,OP03,75.98,2024-04-02 04:00:00,2024-04-02 04:44:00,OK,2,5,7
1041,LINE_D,P009,OP03,78.69,2024-04-04 02:42:00,2024-04-04 03:15:00,OK,3,2,5
1042,LINE_C,P002,OP01,75.86,2024-04-07 15:26:00,2024-04-07 15:55:00,OK,1,2,3
1043,LINE_C,P004,OP03,74.42,2024-04-04 10:22:00,2024-04-04 10:50:00,FAIL,5,2,7
1044,LINE_C,P001,OP01,73.49,2024-04-04 04:34:00,2024-04-04 04:47:00,FAIL,1,4,5
1045,LINE_D,P009,OP04,67.61,2024-04-02 19:43:00,2024-04-02 20:33:00,OK,3,2,5
1046,LINE_A,P006,OP05,71.4,2024-04-02 14:32:00,2024-04-02 14:46:00,OK,2,5,7
1047,LINE_C,P001,OP03,72.7,2024-04-06 05:21:00,2024-04-06 05:39:00,OK,1,3,4
1048,LINE_D,P010,OP02,80.29,2024-04-04 04:08:00,2024-04-04 05:00:00,OK,1,3,4
1049,LINE_B,P006,OP04,76.72,2024-04-03 04:22:00,2024-04-03 04:43:00,OK,4,1,5
1050,LINE_A,P008,OP02,66.18,2024-04-04 08:51:00,2024-04-04 09:11:00,OK,1,4,5
1051,LINE_B,P001,OP02,76.62,2024-04-06 13:41:00,2024-04-06 14:13:00,FAIL,3,2,5
1052,LINE_C,P009,OP04,73.07,2024-04-05 01:38:00,2024-04-05 02:05:00,FAIL,1,3,4
1053,LINE_C,P001,OP01,71.62,2024-04-01 15:32:00,2024-04-01 15:49:00,FAIL,3,2,5
1054,LINE_A,P007,OP05,78.06,2024-04-05 06:23:00,2024-04-05 07:19:00,OK,3,4,7
1055,LINE_B,P006,OP04,80.15,2024-04-04 05:33:00,2024-04-04 05:45:00,OK,4,1,5
1056,LINE_C,P009,OP03,79.66,2024-04-05 02:09:00,2024-04-05 02:58:00,FAIL,3,1,4
1057,LINE_B,P004,OP04,70.8,2024-04-05 01:04:00,2024-04-05 01:39:00,FAIL,3,5,8
1058,LINE_D,P009,OP01,73.45,2024-04-03 07:31:00,2024-04-03 08:20:00,FAIL,5,3,8
1059,LINE_C,P008,OP04,76.66,2024-04-04 14:20:00,2024-04-04 14:43:00,FAIL,4,5,9
1060,LINE_A,P005,OP05,79.88,2024-04-03 18:21:00,2024-04-03 19:03:00,FAIL,4,2,6
1061,LINE_B,P004,OP02,72.6,2024-04-02 09:30:00,2024-04-02 10:28:00,OK,2,3,5
1062,LINE_A,P008,OP04,74.07,2024-04-01 20:37:00,2024-04-01 21:02:00,OK,4,5,9
1063,LINE_B,P001,OP01,69.47,2024-04-05 16:51:00,2024-04-05 17:32:00,FAIL,4,2,6
1064,LINE_A,P009,OP02,69.02,2024-04-03 19:45:00,2024-04-03 20:06:00,OK,5,4,9
1065,LINE_C,P008,OP05,79.06,2024-04-06 12:38:00,2024-04-06 12:56:00,FAIL,4,5,9
1066,LINE_D,P005,OP02,81.78,2024-04-07 13:36:00,2024-04-07 14:14:00,FAIL,2,4,6
1067,LINE_D,P002,OP03,74.64,2024-04-07 06:20:00,2024-04-07 07:01:00,OK,2,3,5
1068,LINE_A,P003,OP02,80.02,2024-04-04 10:11:00,2024-04-04 10:42:00,OK,3,5,8
1069,LINE_A,P007,OP04,76.81,2024-04-05 16:35:00,2024-04-05 17:29:00,FAIL,2,2,4
1070,LINE_B,P007,OP04,71.77,2024-04-07 12:10:00,2024-04-07 12:49:00,OK,4,1,5
1071,LINE_C,P005,OP04,76.81,2024-04-07 21:12:00,2024-04-07 21:46:00,FAIL,4,1,5
1072,LINE_B,P008,OP02,82.69,2024-04-07 10:58:00,2024-04-07 11:55:00,FAIL,5,5,10
1073,LINE_C,P007,OP02,74.82,2024-04-06 07:00:00,2024-04-06 07:41:00,FAIL,1,4,5
1074,LINE_D,P010,OP05,82.82,2024-04-02 18:51:00,2024-04-02 19:40:00,OK,5,1,6
1075,LINE_D,P003,OP01,61.9,2024-04-02 06:55:00,2024-04-02 07:46:00,FAIL,4,2,6
1076,LINE_C,P006,OP04,79.11,2024-04-05 15:31:00,2024-04-05 16:01:00,FAIL,2,4,6
1077,LINE_A,P009,OP01,75.44,2024-04-06 03:06:00,2024-04-06 03:32:00,FAIL,1,4,5
1078,LINE_A,P004,OP02,73.5,2024-04-03 21:13:00,2024-04-03 22:04:00,OK,1,1,2
1079,LINE_A,P010,OP02,75.46,2024-04-03 01:36:00,2024-04-03 02:01:00,FAIL,2,4,6
1080,LINE_A,P003,OP03,65.06,2024-04-04 05:58:00,2024-04-04 06:57:00,OK,3,2,5
1081,LINE_D,P007,OP02,73.9,2024-04-07 22:01:00,2024-04-07 22:12:00,OK,3,5,8
1082,LINE_C,P010,OP01,76.79,2024-04-08 01:40:00,2024-04-08 02:34:00,OK,2,1,3
1083,LINE_A,P009,OP03,82.39,2024-04-05 06:48:00,2024-04-05 07:32:00,OK,4,3,7
1084,LINE_C,P008,OP02,72.41,2024-04-06 02:42:00,2024-04-06 03:23:00,FAIL,1,4,5
1085,LINE_D,P008,OP04,70.96,2024-04-03 08:05:00,2024-04-03 09:01:00,FAIL,5,3,8
1086,LINE_D,P004,OP04,72.49,2024-04-05 00:00:00,2024-04-05 00:25:00,FAIL,1,3,4
1087,LINE_B,P008,OP02,79.58,2024-04-05 03:51:00,2024-04-05 04:02:00,FAIL,4,3,7
1088,LINE_C,P009,OP01,76.64,2024-04-04 06:32:00,2024-04-04 07:03:00,OK,3,5,8
1089,LINE_B,P008,OP04,72.35,2024-04-02 07:22:00,2024-04-02 07:47:00,FAIL,4,4,8
1090,LINE_D,P004,OP03,77.57,2024-04-01 12:42:00,2024-04-01 12:57:00,FAIL,3,2,5
1091,LINE_D,P009,OP03,75.49,2024-04-06 17:13:00,2024-04-06 17:58:00,FAIL,5,3,8
1092,LINE_B,P002,OP02,79.84,2024-04-06 11:54:00,2024-04-06 12:21:00,FAIL,3,3,6
1093,LINE_B,P004,OP04,71.49,2024-04-02 16:38:00,2024-04-02 17:35:00,FAIL,5,2,7
1094,LINE_C,P002,OP02,73.36,2024-04-08 00:59:00,2024-04-08 01:57:00,FAIL,5,5,10
1095,LINE_A,P009,OP02,73.04,2024-04-03 22:07:00,2024-04-03 22:40:00,FAIL,2,3,5
1096,LINE_B,P008,OP01,67.68,2024-04-01 20:25:00,2024-04-01 20:38:00,OK,5,3,8
1097,LINE_D,P006,OP02,76.48,2024-04-07 20:45:00,2024-04-07 21:13:00,OK,4,4,8
1098,LINE_D,P008,OP01,76.31,2024-04-04 04:56:00,2024-04-04 05:36:00,OK,1,1,2
1099,LINE_A,P004,OP01,75.03,2024-04-03 01:25:00,2024-04-03 01:44:00,FAIL,5,3,8
1100,LINE_D,P008,OP04,73.83,2024-04-08 05:33:00,2024-04-08 06:21:00,FAIL,5,2,7
1101,LINE_A,P010,OP01,67.92,2024-04-08 00:42:00,2024-04-08 01:19:00,OK,3,5,8
1102,LINE_B,P003,OP05,72.9,2024-04-03 17:37:00,2024-04-03 18:03:00,OK,1,2,3
1103,LINE_D,P005,OP01,73.29,2024-04-03 02:44:00,2024-04-03 02:54:00,OK,4,4,8
1104,LINE_A,P004,OP03,70.99,2024-04-04 14:40:00,2024-04-04 15:35:00,OK,3,4,7
1105,LINE_B,P005,OP02,74.19,2024-04-06 04:05:00,2024-04-06 04:22:00,OK,5,2,7
1106,LINE_C,P008,OP01,77.02,2024-04-02 00:17:00,2024-04-02 00:37:00,FAIL,3,5,8
1107,LINE_D,P008,OP01,84.43,2024-04-04 19:02:00,2024-04-04 19:56:00,OK,4,3,7
1108,LINE_C,P001,OP01,75.87,2024-04-06 05:58:00,2024-04-06 06:55:00,OK,3,5,8
1109,LINE_A,P003,OP04,76.29,2024-04-07 21:04:00,2024-04-07 21:51:00,FAIL,1,3,4
1110,LINE_D,P002,OP04,74.63,2024-04-04 11:57:00,2024-04-04 12:18:00,FAIL,5,4,9
1111,LINE_B,P006,OP04,65.41,2024-04-05 23:30:00,2024-04-06 00:01:00,FAIL,3,1,4
1112,LINE_A,P008,OP01,74.87,2024-04-04 14:42:00,2024-04-04 15:34:00,FAIL,4,5,9
1113,LINE_A,P009,OP04,75.3,2024-04-04 04:55:00,2024-04-04 05:25:00,FAIL,1,4,5
1114,LINE_D,P008,OP01,87.32,2024-04-01 22:48:00,2024-04-01 23:10:00,OK,5,3,8
1115,LINE_D,P008,OP01,74.04,2024-04-04 08:55:00,2024-04-04 09:40:00,OK,2,3,5
1116,LINE_A,P009,OP04,76.51,2024-04-08 06:15:00,2024-04-08 06:40:00,OK,2,3,5
1117,LINE_B,P008,OP03,74.83,2024-04-03 21:21:00,2024-04-03 21:38:00,FAIL,4,1,5
1118,LINE_D,P009,OP02,69.16,2024-04-06 01:27:00,2024-04-06 02:07:00,FAIL,4,2,6
1119,LINE_A,P005,OP04,80.71,2024-04-03 12:02:00,2024-04-03 12:50:00,FAIL,5,2,7
1120,LINE_C,P010,OP05,78.76,2024-04-07 02:38:00,2024-04-07 03:05:00,FAIL,1,3,4
1121,LINE_C,P006,OP05,78.96,2024-04-03 00:34:00,2024-04-03 01:12:00,FAIL,5,4,9
1122,LINE_D,P004,OP04,70.45,2024-04-06 12:20:00,2024-04-06 12:50:00,OK,2,2,4
1123,LINE_D,P003,OP04,82.01,2024-04-04 22:53:00,2024-04-04 23:50:00,OK,4,4,8
1124,LINE_A,P008,OP01,67.99,2024-04-02 18:28:00,2024-04-02 19:10:00,FAIL,5,3,8
1125,LINE_B,P002,OP04,77.93,2024-04-01 12:11:00,2024-04-01 13:07:00,FAIL,2,4,6
1126,LINE_C,P009,OP04,85.95,2024-04-05 04:26:00,2024-04-05 05:15:00,FAIL,4,1,5
1127,LINE_A,P004,OP03,70.05,2024-04-06 21:14:00,2024-04-06 21:58:00,OK,1,5,6
1128,LINE_D,P003,OP03,72.17,2024-04-02 08:40:00,2024-04-02 09:17:00,OK,1,1,2
1129,LINE_C,P006,OP04,75.5,2024-04-01 20:33:00,2024-04-01 21:03:00,OK,1,3,4
1130,LINE_B,P003,OP02,72.48,2024-04-04 02:40:00,2024-04-04 03:23:00,OK,4,5,9
1131,LINE_D,P010,OP02,67.25,2024-04-08 06:25:00,2024-04-08 06:59:00,OK,5,2,7
1132,LINE_C,P001,OP04,75.34,2024-04-06 13:55:00,2024-04-06 14:45:00,FAIL,3,4,7
1133,LINE_C,P010,OP03,69.69,2024-04-07 13:15:00,2024-04-07 13:35:00,FAIL,1,4,5
1134,LINE_D,P008,OP01,77.37,2024-04-04 04:17:00,2024-04-04 04:56:00,OK,3,2,5
1135,LINE_C,P005,OP01,70.4,2024-04-05 16:08:00,2024-04-05 16:54:00,FAIL,3,5,8
1136,LINE_D,P005,OP02,82.75,2024-04-04 10:57:00,2024-04-04 11:07:00,FAIL,5,1,6
1137,LINE_C,P003,OP01,71.08,2024-04-03 19:48:00,2024-04-03 20:38:00,OK,2,5,7
1138,LINE_C,P003,OP01,73.39,2024-04-04 20:21:00,2024-04-04 21:21:00,FAIL,4,1,5
1139,LINE_B,P003,OP05,79.07,2024-04-05 01:12:00,2024-04-05 02:09:00,FAIL,4,2,6
1140,LINE_C,P008,OP03,68.85,2024-04-07 08:57:00,2024-04-07 09:39:00,FAIL,3,2,5
1141,LINE_B,P007,OP05,76.14,2024-04-02 15:26:00,2024-04-02 16:05:00,FAIL,1,2,3
1142,LINE_C,P009,OP01,81.54,2024-04-02 08:39:00,2024-04-02 09:39:00,FAIL,4,1,5
1143,LINE_D,P006,OP01,66.96,2024-04-05 12:38:00,2024-04-05 13:31:00,OK,3,5,8
1144,LINE_C,P010,OP02,75.92,2024-04-06 16:44:00,2024-04-06 16:55:00,OK,5,5,10
1145,LINE_A,P003,OP01,76.3,2024-04-06 14:46:00,2024-04-06 15:40:00,OK,3,4,7
1146,LINE_B,P009,OP02,78.91,2024-04-04 19:06:00,2024-04-04 19:47:00,FAIL,1,1,2
1147,LINE_B,P007,OP01,68.82,2024-04-06 11:52:00,2024-04-06 12:25:00,FAIL,5,4,9
1148,LINE_B,P008,OP04,68.4,2024-04-05 23:26:00,2024-04-05 23:53:00,OK,1,3,4
1149,LINE_C,P001,OP04,77.61,2024-04-05 11:02:00,2024-04-05 11:18:00,FAIL,3,5,8
1150,LINE_B,P010,OP01,76.48,2024-04-03 11:49:00,2024-04-03 12:06:00,OK,4,1,5
1151,LINE_B,P002,OP05,76.25,2024-04-05 03:04:00,2024-04-05 03:29:00,OK,2,5,7
1152,LINE_B,P010,OP01,76.73,2024-04-08 00:07:00,2024-04-08 00:30:00,FAIL,2,3,5
1153,LINE_B,P002,OP01,71.6,2024-04-02 23:30:00,2024-04-02 23:48:00,OK,5,3,8
1154,LINE_C,P001,OP02,76.16,2024-04-01 12:03:00,2024-04-01 12:35:00,FAIL,2,5,7
1155,LINE_A,P002,OP04,76.47,2024-04-01 22:18:00,2024-04-01 22:36:00,FAIL,4,5,9
1156,LINE_D,P009,OP02,71.43,2024-04-05 10:51:00,2024-04-05 11:33:00,OK,5,1,6
1157,LINE_A,P008,OP04,84.33,2024-04-07 06:23:00,2024-04-07 06:52:00,FAIL,4,1,5
1158,LINE_A,P006,OP05,77.37,2024-04-02 13:28:00,2024-04-02 14:09:00,OK,4,1,5
1159,LINE_C,P007,OP05,69.04,2024-04-02 01:56:00,2024-04-02 02:14:00,FAIL,3,5,8
1160,LINE_A,P002,OP05,78.28,2024-04-06 11:53:00,2024-04-06 12:35:00,OK,5,4,9
1161,LINE_C,P008,OP04,70.13,2024-04-06 05:26:00,2024-04-06 06:04:00,FAIL,2,4,6
1162,LINE_C,P006,OP02,78.94,2024-04-02 09:57:00,2024-04-02 10:27:00,FAIL,4,3,7
1163,LINE_D,P002,OP03,80.79,2024-04-02 02:19:00,2024-04-02 02:34:00,OK,1,1,2
1164,LINE_C,P002,OP04,70.9,2024-04-07 15:55:00,2024-04-07 16:08:00,FAIL,5,5,10
1165,LINE_C,P006,OP01,79.82,2024-04-06 03:29:00,2024-04-06 04:25:00,OK,1,3,4
1166,LINE_A,P006,OP05,77.06,2024-04-03 02:15:00,2024-04-03 03:07:00,FAIL,4,2,6
1167,LINE_B,P007,OP05,79.11,2024-04-02 15:22:00,2024-04-02 16:20:00,OK,3,5,8
1168,LINE_B,P005,OP03,84.48,2024-04-08 06:17:00,2024-04-08 07:09:00,FAIL,3,1,4
1169,LINE_D,P002,OP02,73.77,2024-04-05 07:51:00,2024-04-05 08:01:00,OK,2,2,4
1170,LINE_D,P007,OP04,71.23,2024-04-02 09:03:00,2024-04-02 10:00:00,FAIL,5,2,7
1171,LINE_A,P001,OP02,70.55,2024-04-03 02:58:00,2024-04-03 03:31:00,OK,3,3,6
1172,LINE_D,P007,OP04,70.92,2024-04-01 21:35:00,2024-04-01 22:28:00,FAIL,1,3,4
1173,LINE_A,P006,OP04,74.61,2024-04-06 01:05:00,2024-04-06 01:32:00,OK,2,5,7
1174,LINE_C,P001,OP02,76.71,2024-04-04 13:20:00,2024-04-04 14:13:00,FAIL,5,4,9
1175,LINE_C,P004,OP02,76.38,2024-04-08 03:39:00,2024-04-08 03:52:00,FAIL,1,2,3
1176,LINE_D,P007,OP02,79.14,2024-04-04 15:02:00,2024-04-04 15:32:00,OK,1,1,2
1177,LINE_C,P002,OP04,75.07,2024-04-05 15:49:00,2024-04-05 16:33:00,OK,2,5,7
1178,LINE_C,P010,OP04,82.27,2024-04-06 07:07:00,2024-04-06 07:18:00,FAIL,4,1,5
1179,LINE_A,P006,OP02,73.68,2024-04-06 02:03:00,2024-04-06 02:31:00,FAIL,1,4,5
1180,LINE_B,P007,OP05,88.6,2024-04-05 10:48:00,2024-04-05 11:03:00,FAIL,4,1,5
1181,LINE_C,P004,OP03,78.13,2024-04-07 07:04:00,2024-04-07 07:19:00,OK,4,3,7
1182,LINE_B,P006,OP03,70.71,2024-04-02 04:51:00,2024-04-02 05:33:00,OK,1,5,6
1183,LINE_B,P003,OP05,69.65,2024-04-04 00:31:00,2024-04-04 00:47:00,OK,2,3,5
1184,LINE_D,P010,OP05,77.41,2024-04-02 04:34:00,2024-04-02 04:55:00,FAIL,4,4,8
1185,LINE_D,P008,OP03,73.88,2024-04-04 22:19:00,2024-04-04 22:38:00,FAIL,4,1,5
1186,LINE_A,P005,OP04,78.57,2024-04-08 01:29:00,2024-04-08 01:42:00,FAIL,3,5,8
1187,LINE_A,P002,OP05,77.37,2024-04-01 18:16:00,2024-04-01 18:29:00,FAIL,3,3,6
1188,LINE_D,P010,OP02,74.64,2024-04-06 14:21:00,2024-04-06 15:08:00,FAIL,5,1,6
1189,LINE_A,P008,OP01,70.77,2024-04-08 05:12:00,2024-04-08 05:52:00,FAIL,5,2,7
1190,LINE_B,P008,OP04,67.43,2024-04-02 07:01:00,2024-04-02 07:43:00,OK,2,1,3
1191,LINE_D,P006,OP05,72.77,2024-04-05 11:22:00,2024-04-05 11:55:00,OK,3,4,7
1192,LINE_D,P005,OP03,79.28,2024-04-05 03:22:00,2024-04-05 03:36:00,OK,3,1,4
1193,LINE_C,P005,OP04,76.07,2024-04-05 03:01:00,2024-04-05 03:16:00,OK,5,2,7
1194,LINE_D,P006,OP02,68.77,2024-04-08 02:29:00,2024-04-08 03:24:00,OK,1,3,4
1195,LINE_C,P005,OP02,75.87,2024-04-06 03:37:00,2024-04-06 04:19:00,OK,3,1,4
1196,LINE_B,PD03,OP02,76.93,2024-04-05 05:18:00,2024-04-05 06:17:00,OK,4,2,6
1197,LINE_A,P006,OP05,70.58,2024-04-04 16:46:00,2024-04-04 17:46:00,GOOD,1,5,6
1198,LINE_B,P010,OP02,275.77,2024-04-08 03:05:00,2024-04-08 03:39:00,FAIL,2,2,4
1199,LINE_K,P010,OP03,75.29,2024-04-01 19:55:00,2024-04-01 20:31:00,FAIL,3,2,5
1200,LINE_D,P004,OP03,69.29,2024-04-04 00:37:00,2024-04-03 23:53:00,FAIL,2,3,5

今回はseeds/seed_production_logs.csvの最後5行が検証項目に引っかかるようにしています。

  • 196行目→product_idがPD03でPと3桁の数字に当てはまらない
  • 197行目→statusがOKでもFAILでもない
  • 198行目→tempurtureが275.77度で明らかに高い
  • 199行目→line_idがLINE_KでLINE_AからLINE_Dまでに当てはまらない
  • 200行目→start_timeとend_timeが逆になっている
1196,LINE_B,PD03,OP02,76.93,2024-04-05 05:18:00,2024-04-05 06:17:00,OK,4,2,6
1197,LINE_A,P006,OP05,70.58,2024-04-04 16:46:00,2024-04-04 17:46:00,GOOD,1,5,6
1198,LINE_B,P010,OP02,375.77,2024-04-08 03:05:00,2024-04-08 03:39:00,FAIL,2,2,4
1199,LINE_K,P010,OP03,75.29,2024-04-01 19:55:00,2024-04-01 20:31:00,FAIL,3,2,5
1200,LINE_D,P004,OP03,69.29,2024-04-04 00:37:00,2024-04-03 23:53:00,FAIL,2,3,5

それでは実行していきましょう。プロジェクトのあるディレクトリでdbt buildを実行

dbt build

実行すると以下のような返答がかえってくると思います。

dbt testの実行結果

想定通りに5個の検証項目でfailになっていますね。成功です。

まとめ

今回はdbt-expectationsを使って、dbt testでは手間のかかる検証ををやってみました。個人的にはIDを正規表現でテストできるのはありがたいと思いました。扱うデータによって使える検証項目は様々だと思います。ぜひ実際にご自身で気になる検証項目を試してみてください!

またdbtについて興味のある方は、ぜひこちらのブログもご覧ください!

BigQueryとSnowflakeのLLM関数を比較してみた前のページ

進化学に倣う最適化手法「遺伝的アルゴリズム」次のページ赤の女王

ピックアップ記事

  1. 最速で理解したい人のためのIT用語集

関連記事

  1. dbt

    TROCCO dbt連携編

    こんにちは、エクチュアの照沼です。前回のブログでTR…

  2. dbt

    dbt Cloud使ってみた

    こんにちは、中村です。データ界隈で名前を聞かない日がないdbtですが…

  3. dbt

    Snowflake Summit 2025 参加レポート【Day3】

    こんにちは、エクスチュアの黒岩です。Snowflake Su…

  4. Trying Out dbt Fusion

    dbt

    dbt Fusion使ってみた

    こんにちは、中村です。先日dbt meetup #14に参加…

カテゴリ
最近の記事
  1. Adobe WebSDK FPIDでECIDの復元を検証
  2. dbt Projects on Snowflakeで作成した…
  3. Dataformでtype:’increment…
  4. dbt Projects on SnowflakeをTASK…
  5. AWS発のAIエージェントIDE「Kiro」を使用した仕様駆…
  1. Metabase

    Metabotを使ってSlackにMetabaseのグラフを投稿する
  2. Adobe Analytics

    イベント前の時間とは-Adobe Analyticsの指標説明
  3. Google Apps Script(GAS)

    文字列置換アプリを作成しました
  4. Mouseflow

    mouseflowによる分析の観点
  5. Adobe Analytics

    Adobe Analytics: データフィードをGoogle BigQuery…
PAGE TOP