はじめに
私は普段の仕事で生成AIを活用することは多いのですが、最近は生成AIが作成したドキュメントやコードが正しいかをレビューする機会が増えてきました。
自分がレビューできる内容であればよいですが、そうでない場合最低限は自身でその技術を理解する必要があります。
AIにコードを解説してもらう方法もありますが、今回は生成AIにハンズオン資料を作成させ、それを使って迅速に理解ができるかを試してみることにします。
利用するための最低限の理解ができればよく、正確性よりもキャッチアップ速度を優先しているので、多少間違っている内容が書かれていてもご容赦ください。READMEの最初にも注意書きを記載しています
ハンズオン資料
作成したハンズオン資料はGitHubにアップしています。
https://github.com/handy-dd18/dbt-hands-on
ハンズオン題材
今回の題材としては、以前学習した際に机上学習途中で止まってしまっていたdbt(data build tool)のハンズオンを作成してみました。
実施プロンプトをメモしておくのを失念してしまったのですが、「Web検索して初心者向けのdbtハンズオン資料を作成してください。Dockerを使用してローカルPC上でハンズオンが完結するようにしてください」レベルのシンプルな指示しかしていません。
Claude Coodeを利用し、モデルはClaude Opus 4.5を使いました。
進め方
進め方としては、最初に作成されたREADME.mdファイルを見ながらハンズオンを進め、説明や手順が不足していると感じた箇所があれば、都度生成AIによる修正を入れながら理解をしていく、という方法を取ることにします。
ハンズオン実施
dbtとは
dbtについて次の説明がされています。概ね自分の理解と一致してそうです。
dbt(data build tool)は、データウェアハウス内でのデータ変換を行うツールです。
特徴:
・ELT(Extract, Load, Transform)の「T(Transform)」を担当
・SQLベースでデータ変換パイプラインを構築
・バージョン管理、テスト、ドキュメント生成が可能
・ソフトウェアエンジニアリングのベストプラクティスをデータ分析に適用
前提条件
前提条件は以下の2つのみです。
・Docker / Docker Compose がインストールされていること
・ターミナル(コマンドライン)の基本操作ができること
ハンズオン構成
ハンズオン構成は以下のようになっています。
これだけだと分かりづらかったので、追加で解説もしてもらいました。
dbt_handson/
├── docker-compose.yml # Docker環境定義
├── Dockerfile # dbtコンテナのビルド設定
├── init/ # PostgreSQL初期化スクリプト
│ └── 01_create_tables.sql
└── dbt_project/ # dbtプロジェクト
├── dbt_project.yml # プロジェクト設定
├── profiles.yml # 接続設定
├── models/ # SQLモデル
│ ├── staging/ # ステージング層
│ └── marts/ # マート層
├── seeds/ # CSVマスターデータ
├── tests/ # カスタムテスト
└── macros/ # 再利用可能なSQL関数
(追加分)ハンズオン構成解説
dbtを利用するにはdbtプロジェクトを作成する必要がありますが、元々のREADMEには説明がなかったので追加してもらいました。
何となく分かるような分からないような、という感じです。

dbtプロジェクトと接続設定についての説明はわかりやすいです。

初見だとこのあたりがどう違うのかが分かりづらかったのですが、この説明を読むと何となく違いが理解できます。

modelsディレクトリが何故stagingとmartsに分かれているかの説明もされています。

ここまでの内容を読んで、dbtのできることや構成などが何となく理解できました。
次は実際にハンズオンを進めていきます。
Step 1: 環境の起動
git cloneコマンドは実施済みの想定で、次のコマンドを実行してDockerを起動します。
cd dbt_handson
docker compose up -d
Docker起動時に以下のエラーが発生しました。
~略~
[+] Running 4/4
✔ Network dbt-hands-on_default Created 0.4s
✔ Volume "dbt-hands-on_postgres_data" Created 0.1s
✘ Container dbt_postgres Error 0.5s
✔ Container dbt_container Created 0.4s
dependency failed to start: container dbt_postgres exited (1)
エラー調査してもらうとパーミッション不足が問題のようでしたので、修正して正常起動を確認後、READMEファイルにも注意書きを追加してもらいました。
原因が特定できました。init/01_create_tables.sqlのパーミッションが不足しており、PostgreSQLが読み取れていません。
Dockerが起動されていると、以下のコマンドでdbtコンテナに入ります。
docker compose exec dbt bash
dbtコンテナ内でdbt debugコマンドを実行して接続確認をします。
初回実行だと次のエラーが発生しました。
# dbt debug
04:50:51 Running with dbt=1.10.15
04:50:51 dbt version: 1.10.15
04:50:51 python version: 3.11.14
04:50:51 python path: /usr/local/bin/python3.11
04:50:51 os info: Linux-6.6.87.2-microsoft-standard-WSL2-x86_64-with-glibc2.41
04:50:51 Connection test: [OK connection ok]
~略~
04:50:51 1 check failed:
04:50:51 Error from git --help: Could not find command, ensure it is in the user's PATH: "git"
エラー調査してgitがインストールされていないことが原因だったので、修正して正常実行まで確認しました。
dbtコンテナにgitがインストールされていないエラーです。Dockerfileを確認して修正します。
次は想定どおりの出力がされました。
root@26dd1f77bc88:/dbt# dbt debug
~略~
04:59:56 Connection test: [OK connection ok]
04:59:56 All checks passed!
Step 2: dbtプロジェクトの構造を理解する
ここではリポジトリ内の主要ファイル内容などの説明がされていますが、これだけだと少しわかりづらいので、説明を追加してもらいます。

追加説明
追加でdbt_project.ymlとprofiles.yml以外のファイルについても説明を追加してもらいました。
外部データソースをsources.ymlで定義することでdbtの記法で指定できるようにしています。

ステージング層では、FROM {{ source('raw_data', 'customers') }} で外部データソースを参照できます。

staging/ディレクトリ配下にあるschema.ymlでは、stg_customers.sqlで定義したモデル?のテストが定義されています。
not nullやuniqueがあることから、データレコード自体に対してのチェックが行われるようです。

データマート層では、ステージング層で定義したモデルを元に複雑な加工処理を行っています。

{{ ref('order_status_master') }}でSeedのテーブルを参照しています。
こちらの内容はStep3で確認します。

マート層もステージング層と同じようにschema.ymlファイルでテストが定義されています。

Step 3: Seedの実行
次はSeedの実行を実施していきます。
先ほどの説明では、Seedとはマスターデータ等を置くと記載されていました。

Step1で入ったdbtコンテナ上でcatコマンドを実行すると、ファイルの内容が確認できます。
注文ステータスの情報が含まれているようです。
# cat seeds/order_status_master.csv
status_code,status_label,description
completed,完了,注文が完了した状態
pending,処理中,注文が処理中の状態
cancelled,キャンセル,注文がキャンセルされた状態
そのあとは「Seedを実行」とだけ記載されていますが、dbt seedがどのようなことをするのかイマイチわかっていないため、解説を追加してもらいます。

追加説明
正しいかわかっていないですが、コマンド実行時の流れも追記されていました。

ファイルの関係を読むと、ファイル名やcsvの構成は気にする必要がありそうです。

seedsディレクトリにもテスト・ドキュメント定義ファイルが作成されています。

dbt seedを実行すると次のログが出力されました。
# dbt seed
05:52:51 Running with dbt=1.10.15
05:52:52 Registered adapter: postgres=1.9.1
05:52:53 Unable to do partial parsing because saved manifest not found. Starting full parse.
05:52:59 [WARNING][MissingArgumentsPropertyInGenericTestDeprecation]: Deprecated
functionality
Found top-level arguments to test `relationships`. Arguments to generic tests
should be nested under the `arguments` property.`
05:53:01 Found 4 models, 17 data tests, 1 seed, 2 sources, 460 macros
05:53:01
05:53:01 Concurrency: 4 threads (target='dev')
05:53:01
05:53:03 1 of 1 START seed file dbt_dev.order_status_master ............................. [RUN]
05:53:04 1 of 1 OK loaded seed file dbt_dev.order_status_master ......................... [INSERT 3 in 0.83s]
05:53:04
05:53:04 Finished running 1 seed in 0 hours 0 minutes and 2.27 seconds (2.27s).
05:53:04
05:53:04 Completed successfully
05:53:04
05:53:04 Done. PASS=1 WARN=0 ERROR=0 SKIP=0 NO-OP=0 TOTAL=1
05:53:04 [WARNING][DeprecationsSummary]: Deprecated functionality
Summary of encountered deprecations:
- MissingArgumentsPropertyInGenericTestDeprecation: 3 occurrences
To see all deprecation instances instead of just the first occurrence of each,
run command again with the `--show-all-deprecations` flag. You may also need to
run with `--no-partial-parse` as some deprecations are only encountered during
parsing.
どのCSVが読み込まれたかまでは出力されていませんが、スキーマ名とテーブル名、INSERTされたレコード数は一致してそうなので問題なさそうです。
05:53:03 1 of 1 START seed file dbt_dev.order_status_master ............................. [RUN]
05:53:04 1 of 1 OK loaded seed file dbt_dev.order_status_master ......................... [INSERT 3 in 0.83s]
Step 4: モデルの実行
seedのロードができたところで、dbtモデルを作成していきます。
「2.2 モデルの階層構造」で記載されている構成ですが、models/ディレクトリ配下の*.sqlに一致するファイル1つがモデル1つに対応します。
models/
├── staging/ # ステージング層:生データのクリーニング
│ ├── stg_customers.sql
│ ├── stg_orders.sql
│ ├── sources.yml # ソース定義
│ └── schema.yml # テスト・ドキュメント
└── marts/ # マート層:ビジネスロジックの適用
├── customer_orders.sql
├── order_status_summary.sql
└── schema.yml
各SQLファイルの内容はStep2で確認したので割愛し、以下のコマンドでモデルを実行していきます。
dbt run
ログを見るとPASS=4とあるので、ステージング層の2モデルとマート層の2モデル、合計4モデルの実行が完了したようです。
# dbt run
06:02:45 Running with dbt=1.10.15
06:02:46 Registered adapter: postgres=1.9.1
06:02:47 Found 4 models, 17 data tests, 1 seed, 2 sources, 460 macros
06:02:47
06:02:47 Concurrency: 4 threads (target='dev')
06:02:47
06:02:48 1 of 4 START sql view model dbt_dev.stg_customers .............................. [RUN]
06:02:48 2 of 4 START sql view model dbt_dev.stg_orders ................................. [RUN]
06:02:49 2 of 4 OK created sql view model dbt_dev.stg_orders ............................ [CREATE VIEW in 0.65s]
06:02:49 1 of 4 OK created sql view model dbt_dev.stg_customers ......................... [CREATE VIEW in 0.65s]
06:02:49 3 of 4 START sql table model dbt_dev.order_status_summary ...................... [RUN]
06:02:49 4 of 4 START sql table model dbt_dev.customer_orders ........................... [RUN]
06:02:49 3 of 4 OK created sql table model dbt_dev.order_status_summary ................. [SELECT 3 in 0.41s]
06:02:49 4 of 4 OK created sql table model dbt_dev.customer_orders ...................... [SELECT 5 in 0.41s]
06:02:49
06:02:49 Finished running 2 table models, 2 view models in 0 hours 0 minutes and 1.65 seconds (1.65s).
06:02:49
06:02:49 Completed successfully
06:02:49
06:02:49 Done. PASS=4 WARN=0 ERROR=0 SKIP=0 NO-OP=0 TOTAL=4
ログの以下の出力順を見る限りだと、1と2、3と4は並列で実行されているようです。
06:02:48 1 of 4 START sql view model dbt_dev.stg_customers .............................. [RUN]
06:02:48 2 of 4 START sql view model dbt_dev.stg_orders ................................. [RUN]
06:02:49 2 of 4 OK created sql view model dbt_dev.stg_orders ............................ [CREATE VIEW in 0.65s]
06:02:49 1 of 4 OK created sql view model dbt_dev.stg_customers ......................... [CREATE VIEW in 0.65s]
06:02:49 3 of 4 START sql table model dbt_dev.order_status_summary ...................... [RUN]
06:02:49 4 of 4 START sql table model dbt_dev.customer_orders ........................... [RUN]
06:02:49 3 of 4 OK created sql table model dbt_dev.order_status_summary ................. [SELECT 3 in 0.41s]
06:02:49 4 of 4 OK created sql table model dbt_dev.customer_orders ...................... [SELECT 5 in 0.41s]
本記事では割愛しますが、--selectオプションを使うことで、特定のモデルだけ実行したり、そのモデル以降の処理すべてを実行することもできるようです。

dbt run時の並列実行と同時実行の仕組みが気になったので追加で解説してもらいました
追加説明
追加された説明によると、実行順序を制御する定義はなく、SQLファイル内の依存関係で順番が決定されるようです。

実行順序があるようなモデルは依存関係があるので、明示的に実行順序を定義する必要はないということでしょうか。
あまりないかと思いますが、依存関係はないけど、実行順序を制御したいケースがあった時はどうするのかは気になりました。

Step 5: テストの実行
この手順ではdbtテストを実行します。
schema.ymlファイルに定義した組み込みテストと、SQLファイルを使ったカスタムテストがあります。


dbtテストは以下のコマンドで実行できます。
dbt test
実際に実行した際のログは以下です。
全部で17個のテストがあり、4並列で実行されています。
# dbt test
06:20:48 Running with dbt=1.10.15
06:20:50 Registered adapter: postgres=1.9.1
06:20:51 Found 4 models, 17 data tests, 1 seed, 2 sources, 460 macros
06:20:51
06:20:51 Concurrency: 4 threads (target='dev')
06:20:51
06:20:52 1 of 17 START test accepted_values_customer_orders_customer_tier__Gold__Silver__Bronze [RUN]
06:20:52 2 of 17 START test accepted_values_stg_orders_status__completed__pending__cancelled [RUN]
06:20:52 3 of 17 START test assert_positive_order_amounts ............................... [RUN]
06:20:52 4 of 17 START test not_null_customer_orders_customer_id ........................ [RUN]
06:20:52 3 of 17 PASS assert_positive_order_amounts ..................................... [PASS in 0.63s]
06:20:52 4 of 17 PASS not_null_customer_orders_customer_id .............................. [PASS in 0.62s]
06:20:52 5 of 17 START test not_null_order_status_master_status_code .................... [RUN]
06:20:52 1 of 17 PASS accepted_values_customer_orders_customer_tier__Gold__Silver__Bronze [PASS in 0.68s]
06:20:52 2 of 17 PASS accepted_values_stg_orders_status__completed__pending__cancelled .. [PASS in 0.68s]
06:20:52 6 of 17 START test not_null_order_status_summary_status ........................ [RUN]
06:20:52 7 of 17 START test not_null_stg_customers_customer_id .......................... [RUN]
06:20:52 8 of 17 START test not_null_stg_customers_email ................................ [RUN]
06:20:53 5 of 17 PASS not_null_order_status_master_status_code .......................... [PASS in 0.25s]
06:20:53 6 of 17 PASS not_null_order_status_summary_status .............................. [PASS in 0.25s]
06:20:53 9 of 17 START test not_null_stg_orders_customer_id ............................. [RUN]
06:20:53 10 of 17 START test not_null_stg_orders_order_id ............................... [RUN]
06:20:53 7 of 17 PASS not_null_stg_customers_customer_id ................................ [PASS in 0.26s]
06:20:53 8 of 17 PASS not_null_stg_customers_email ...................................... [PASS in 0.26s]
06:20:53 11 of 17 START test relationships_stg_orders_customer_id__customer_id__ref_stg_customers_ [RUN]
06:20:53 12 of 17 START test unique_customer_orders_customer_id ......................... [RUN]
06:20:53 9 of 17 PASS not_null_stg_orders_customer_id ................................... [PASS in 0.30s]
06:20:53 10 of 17 PASS not_null_stg_orders_order_id ..................................... [PASS in 0.30s]
06:20:53 13 of 17 START test unique_order_status_master_status_code ..................... [RUN]
06:20:53 14 of 17 START test unique_order_status_summary_status ......................... [RUN]
06:20:53 11 of 17 PASS relationships_stg_orders_customer_id__customer_id__ref_stg_customers_ [PASS in 0.34s]
06:20:53 12 of 17 PASS unique_customer_orders_customer_id ............................... [PASS in 0.34s]
06:20:53 15 of 17 START test unique_stg_customers_customer_id ........................... [RUN]
06:20:53 16 of 17 START test unique_stg_customers_email ................................. [RUN]
06:20:53 13 of 17 PASS unique_order_status_master_status_code ........................... [PASS in 0.30s]
06:20:53 14 of 17 PASS unique_order_status_summary_status ............................... [PASS in 0.30s]
06:20:53 17 of 17 START test unique_stg_orders_order_id ................................. [RUN]
06:20:53 15 of 17 PASS unique_stg_customers_customer_id ................................. [PASS in 0.28s]
06:20:53 16 of 17 PASS unique_stg_customers_email ....................................... [PASS in 0.28s]
06:20:53 17 of 17 PASS unique_stg_orders_order_id ....................................... [PASS in 0.15s]
06:20:53
06:20:53 Finished running 17 data tests in 0 hours 0 minutes and 2.51 seconds (2.51s).
06:20:54
06:20:54 Completed successfully
06:20:54
06:20:54 Done. PASS=17 WARN=0 ERROR=0 SKIP=0 NO-OP=0 TOTAL=17
どの定義がどのテストに一致しているのかわかりにくかったので、追加で説明をしてもらいました。
追加説明分
これをみると先にテストの種類名が付く命名になっているようです。

カスタムテストはファイル名がそのままテスト名になるようなのでわかりやすいです。

組み込みテストのほうは、「テスト種類」・「モデル.カラム名」などで使われるので、どのテストか特定したい場合は、テスト名からモデル名とカラム名を探すと見つけやすそうです。

Step 6: ドキュメントの生成
dbtにはデータリネージを表示するなどの機能が提供されています。

以下のコマンドでdbtドキュメントを生成できます。
dbt docs generate
実行するとtarget/catalog.jsonファイルが生成されます。
# dbt docs generate
06:37:37 Running with dbt=1.10.15
06:37:38 Registered adapter: postgres=1.9.1
06:37:39 Found 4 models, 17 data tests, 1 seed, 2 sources, 460 macros
06:37:39
06:37:39 Concurrency: 4 threads (target='dev')
06:37:39
06:37:40 Building catalog
06:37:41 Catalog written to /dbt/target/catalog.json
生成されたファイルだけで見ようとすると中々に辛いものがあります。
# cat target/catalog.json
{"metadata": {"dbt_schema_version": "https://schemas.getdbt.com/dbt/catalog/v1.json", "dbt_version": "1.10.15", "generated_at": "2025-12-25T06:37:41.020135Z", "invocation_id": "d266c1c2-9069-484d-8b44-74f2a34e2198", "invocation_started_at": "2025-12-25T06:37:37.671482Z", "env": {}}, "nodes": {"model.dbt_handson.customer_orders": {"metadata": {"type": "BASE TABLE", "schema": "dbt_dev", "name": "customer_orders", "database": "dbt_handson", "comment": null, "owner": "postgres"}, "columns": {"customer_id": {"type": "integer", "index": 1, "name": "customer_id", "comment": null}, "full_name": {"type": "text", "index": 2, "name": "full_name", "comment": null}, "email": {"type": "character varying(100)", "index": 3, "name": "email", "comment": null}, "total_orders": {"type": "bigint", "index": 4, "name": "total_orders", "comment": null}, "total_spent": {"type": "numeric", "index": 5, "name": "total_spent", "comment": null}, "first_order_date": {"type": "date", "index": 6, "name": "first_order_date", "comment": null}, "last_order_date": {"type": "date", "index": 7, "name": "last_order_date", "comment": null}, "customer_tier": {"type": "text", "index": 8, "name": "customer_tier", "comment": null}}, "stats": {"has_stats": {"id": "has_stats", "label": "Has Stats?", "value": false, "include": false, "description": "Indicates whether there are statistics for this table"}}, "unique_id": "model.dbt_handson.customer_orders"}, "seed.dbt_handson.order_status_master": {"metadata": {"type": "BASE TABLE", "schema": "dbt_dev", "name": "order_status_master", "database": "dbt_handson", "comment": null, "owner": "postgres"}, "columns": {"status_code": {"type": "text", "index": 1, "name": "status_code", "comment": null}, "status_label": {"type": "text", "index": 2, "name": "status_label", "comment": null}, "description": {"type": "text", "index": 3, "name": "description", "comment": null}}, "stats": {"has_stats": {"id": "has_stats", "label": "Has Stats?", "value": false, "include": false, "description": "Indicates whether there are statistics for this table"}}, "unique_id": "seed.dbt_handson.order_status_master"}, "model.dbt_handson.order_status_summary": {"metadata": {"type": "BASE TABLE", "schema": "dbt_dev", "name": "order_status_summary", "database": "dbt_handson", "comment": null, "owner": "postgres"}, "columns": {"status": {"type": "character varying(20)", "index": 1, "name": "status", "comment": null}, "status_label": {"type": "text", "index": 2, "name": "status_label", "comment": null}, "order_count": {"type": "bigint", "index": 3, "name": "order_count", "comment": null}, "total_amount": {"type": "numeric", "index": 4, "name": "total_amount", "comment": null}, "avg_amount": {"type": "numeric", "index": 5, "name": "avg_amount", "comment": null}}, "stats": {"has_stats": {"id": "has_stats", "label": "Has Stats?", "value": false, "include": false, "description": "Indicates whether there are statistics for this table"}}, "unique_id": "model.dbt_handson.order_status_summary"}, "model.dbt_handson.stg_customers": {"metadata": {"type": "VIEW", "schema": "dbt_dev", "name": "stg_customers", "database": "dbt_handson", "comment": null, "owner": "postgres"}, "columns": {"customer_id": {"type": "integer", "index": 1, "name": "customer_id", "comment": null}, "first_name": {"type": "character varying(50)", "index": 2, "name": "first_name", "comment": null}, "last_name": {"type": "character varying(50)", "index": 3, "name": "last_name", "comment": null}, "full_name": {"type": "text", "index": 4, "name": "full_name", "comment": null}, "email": {"type": "character varying(100)", "index": 5, "name": "email", "comment": null}, "created_at": {"type": "timestamp without time zone", "index": 6, "name": "created_at", "comment": null}}, "stats": {"has_stats": {"id": "has_stats", "label": "Has Stats?", "value": false, "include": false, "description": "Indicates whether there are statistics for this table"}}, "unique_id": "model.dbt_handson.stg_customers"}, "model.dbt_handson.stg_orders": {"metadata": {"type": "VIEW", "schema": "dbt_dev", "name": "stg_orders", "database": "dbt_handson", "comment": null, "owner": "postgres"}, "columns": {"order_id": {"type": "integer", "index": 1, "name": "order_id", "comment": null}, "customer_id": {"type": "integer", "index": 2, "name": "customer_id", "comment": null}, "order_date": {"type": "date", "index": 3, "name": "order_date", "comment": null}, "status": {"type": "character varying(20)", "index": 4, "name": "status", "comment": null}, "amount": {"type": "numeric(10,2)", "index": 5, "name": "amount", "comment": null}}, "stats": {"has_stats": {"id": "has_stats", "label": "Has Stats?", "value": false, "include": false, "description": "Indicates whether there are statistics for this table"}}, "unique_id": "model.dbt_handson.stg_orders"}}, "sources": {"source.dbt_handson.raw_data.customers": {"metadata": {"type": "BASE TABLE", "schema": "raw_data", "name": "customers", "database": "dbt_handson", "comment": null, "owner": "postgres"}, "columns": {"customer_id": {"type": "integer", "index": 1, "name": "customer_id", "comment": null}, "first_name": {"type": "character varying(50)", "index": 2, "name": "first_name", "comment": null}, "last_name": {"type": "character varying(50)", "index": 3, "name": "last_name", "comment": null}, "email": {"type": "character varying(100)", "index": 4, "name": "email", "comment": null}, "created_at": {"type": "timestamp without time zone", "index": 5, "name": "created_at", "comment": null}}, "stats": {"has_stats": {"id": "has_stats", "label": "Has Stats?", "value": false, "include": false, "description": "Indicates whether there are statistics for this table"}}, "unique_id": "source.dbt_handson.raw_data.customers"}, "source.dbt_handson.raw_data.orders": {"metadata": {"type": "BASE TABLE", "schema": "raw_data", "name": "orders", "database": "dbt_handson", "comment": null, "owner": "postgres"}, "columns": {"order_id": {"type": "integer", "index": 1, "name": "order_id", "comment": null}, "customer_id": {"type": "integer", "index": 2, "name": "customer_id", "comment": null}, "order_date": {"type": "date", "index": 3, "name": "order_date", "comment": null}, "status": {"type": "character varying(20)", "index": 4, "name": "status", "comment": null}, "amount": {"type": "numeric(10,2)", "index": 5, "name": "amount", "comment": null}}, "stats": {"has_stats": {"id": "has_stats", "label": "Has Stats?", "value": false, "include": false, "description": "Indicates whether there are statistics for this table"}}, "unique_id": "source.dbt_handson.raw_data.orders"}}, "errors": null}
以下のコマンドを実行して、ブラウザでhttp://localhost:8080にアクセスすると、ブラウザからモデルの内容が確認できます。
dbt docs serve --port 8080
Step 7: その他の便利なコマンド
最後に他のdbtコマンドを確認して、後片付けをして終了です。

おわりに
ここまででコメントした修正内容は全てGitHubに反映しました。
一通りハンズオンを実施したことで理解が進んだのはもちろんですが、進めていて「この仕組みはどうなってるのか?」みたいな疑問が出たときに、時間をかけずに調査→理解→文書化のサイクルを高速に回すことができたので、寧ろその作業の方がより理解につながったと思いました。
普段触っていない技術について学ぶ際は知らないワードが多く、**「オフチョベットしたテフをマブガッドしてリット」(画像略)**のような状態になりがちです。
また、学びたいと思った時に適切なハンズオンが見つからなかったり、アップデートで動かなかったりすることもあるかもしれません。
そんなときには生成AIを使って自分のためのハンズオンを作って学習する方法もできそうだなと思い、この記事を書いてみました。
興味ある方は是非ご自身でも試されてみてください。
生成AIを使う以上ハルシネーション等の問題はありますが、実際に手を動かすことで実装エラー等にはすぐに気が付くことができるので、それとプロンプトなどを工夫していくことで、ある程度の質は担保されるのでないかと思いました
この記事がどなたかの参考になれば幸いです。



