
dbt ChartsでダッシュボードまでAIに作ってもらう
こんにちは。大石です。
dbt Labsがdbt Chartsを公開しました。YAMLでダッシュボードを定義し、dbtプロジェクトと同じリポジトリで管理できるツールです。2026年9月14日に、言語・エンジン・dct CLIがApache-2.0で公開され、同時にホスト版のdbtCharts.comもパブリックベータで始まっています。
BigQueryの公開データセットを題材に、インストールからダッシュボードの表示までを試しました。dbtのモデル作成からYAMLの記述まで、実作業はClaude Codeに任せています。
目次
dbt Chartsとは
SQLで「どのデータを見るか」を書き、YAMLで「どう見せるか」を宣言すると、インタラクティブなダッシュボードが出来上がる、という仕組みです。処理の流れは、YAMLのコンパイル(検証、テーマとレイアウトの解決)、dbtアダプタ経由でのクエリ実行、Vega-Liteでの描画、という3段階になっています。
特徴的なのは、これがBIツールのGUIではなくテキストファイルである点です。dbtのモデルと同じようにGitで管理し、差分を見て、PRでレビューできます。
出力はHTML・PDF・PNG・SVG・JSONに対応し、チャートは16種類、テーマは5種類が組み込みです。インストールせずに触るなら play.dbtcharts.com で試せます。
YAMLであることの意味
dbtリポジトリと一緒に管理できる
ダッシュボードのファイルをdbtプロジェクトの中に置くため、ブランチでモデルを変更すると、そのブランチのダッシュボードも一緒に変わります。モデルの修正とダッシュボードの修正が1つのPRに収まるため、両者を突き合わせてレビューできます。
クエリの中ではref()やsource()が使えます。CIに組み込めば、参照切れをPRの時点で検出できます。dct impact <column>というコマンドもあり、ある列を参照しているボードを一覧できます。
AIに書かせやすい
dbt Labs自身が、AIエージェントが作ったダッシュボードは成果物やデータ変換が散らばって監査しにくい、という課題意識を公言しています。dbt Chartsの構文は、エージェントが書きやすく、人間がレビューしやすい形を狙って設計されています。
実際に使うと、dct validateとdct renderが便利でした。AIが書く、検証する、画像に出して確認する、直す、というループをAI自身で回せます。GUIのBIツールでは、この「生成して自分で確かめる」部分が成立しにくいことが課題でした。
エージェント向けのスキルとMCPサーバーも同梱されていて、Claude Code・Cursor・VS Code・Codexなどに導入できます。
試した構成
- データ:BigQuery公開データセット
bigquery-public-data.thelook_ecommerce - 変換:dbt Core 1.12 + dbt-bigquery
- 可視化:dbt Charts(
dct0.7.1)
環境の準備
dbt Charts本体は、dbtとは別の環境に入れます。ここだけは注意が必要です。
uv tool install "dbt-charts[bigquery]"
dct --version同じ環境にdbtと同居させると、dbt v2を使っている場合にdbtが1.x系へ置き換わってしまいます。uv tool installで独立した環境に入れておくのが安全です。BigQuery以外を使う場合は、[snowflake]、[postgresql]、[redshift]、[databricks] などのオプションを指定します。
まず何が入っているかを確認します。
python3 -V # 3.10 以上
uv --version
gcloud --version
bq version
dbt --version
claude --version足りないものを入れます(macOS / Homebrewの場合)。
brew install uv
brew install --cask google-cloud-sdk
npm install -g @anthropic-ai/claude-code
# dbt(BigQueryアダプタ込み)
uv tool install dbt-core --with dbt-bigqueryこの組み合わせで dbt-core 1.12.5 と dbt-bigquery 1.12.1 が入りました。
gcloud auth login
gcloud config set project <YOUR_GCP_PROJECT_ID>
gcloud auth application-default login # dbt と dct が使う認証
bq --location=US ls bigquery-public-data:thelook_ecommerceテーブル一覧が返ってくれば準備完了です。thelook_ecommerce は US にあるので、ロケーションは US を指定します。
プロジェクトを作る
dbt init thelook
cd thelook
dbt debug続いて、同じディレクトリでdbt Chartsを初期化します。
dct init # charts/ と dbt_charts.yml を作成
dct init skills claude # Claude Code 用のスキルを .claude/skills に導入dbt_charts.ymlには接続を明示しておきます。
sources:
analytics:
type: dbt_profile
profile: thelook
target: devこれで、dbtプロジェクトの中にcharts/が同居する構成ができました。
Claude Codeにデータを調べさせる
claude を起動して、まずデータセットの中身を調べてもらいます。モデルの設計をいきなり指示するのではなく、先に実データを見てもらうのがポイントです。
— プロンプト
BigQueryの公開データセットbigquery-public-data.thelook_ecommerceを調べてください。bqコマンドを使い、参照のみ・書き込みなしでお願いします。1. テーブル一覧と、各テーブルのスキーマ・行数
2. テーブル間の結合キーと関係
3.orders/order_itemsの期間、ステータスの種類と分布、金額の分布
4.usersの地域・流入元、productsのカテゴリとブランドの種類数クエリを実行する前に必ず
bq query --dry_run --use_legacy_sql=falseでスキャン量を見積もり、大きいものは日付やLIMITで絞ってください。ロケーションは US です。調査結果はdocs/dataset-notes.mdにまとめてください。
ステータスの種類や日付の範囲を先に把握させておくと、この後のモデルで「Cancelled と Returned をどう扱うか」といった判断を自分でしてくれます。
dbtモデルを作らせる
— プロンプト
先ほどの調査結果をもとに、このdbtプロジェクトに売上ダッシュボード用のモデルを作ってください。・
models/staging/にbigquery-public-data.thelook_ecommerceをソースとした stg モデル(sources.yml も作成、命名はdbtのベストプラクティスに従う)
・models/marts/に、日次の売上・注文数・購入者数、商品カテゴリ別、地域別、流入元別で集計できる粒度のモデル
・キャンセル・返品ステータスの扱いを明示し、集計から除外するか区別できるようにする
・staging は view、marts は table
・schema.ymlに主キーの unique / not_null テストを付ける作成後に
dbt buildを実行し、通るまで直してください。公開データセットは読み取り専用なので、書き込み先は profiles.yml のthelook_dbtデータセットです。
ここは通常のdbt開発と同じです。dbt buildが通るまで自分で直してくれます。
dbt Chartsで可視化する
— プロンプト
dctを使って、marts モデルからダッシュボードを1枚作ってください。.claude/skillsの dbt charts スキルとdct docsを先に読んでから書いてください。・
charts/sales.ymlに、KPI(売上・注文数・平均単価)、月次の推移、カテゴリ別、地域別、明細テーブルを配置
・フィルターは期間(daterange)、カテゴリ、地域
・クエリはref()でモデルを参照し、source: analyticsを使う
・各クエリのWHERE句にフィルターを直接書く。別クエリを{{ queries.x }}で組み込む形は避ける
・tabs:とdetails:は使わない。日本語のラベルは短くする完成したら
dct validate charts/sales.yml --strictとdct render charts/sales.yml --format pngを実行し、画像を確認して崩れがあれば直してください。
WHERE句やタブに関する条件は、後述の「つまずいた点」で踏んだ不具合を避けるためのものです。最初から伝えておくと手戻りがありません。
出来たら、ブラウザで確認します。
dct serveターミナルに表示されたURLを開くと、フィルター付きのダッシュボードが動きます。

title: 売上ダッシュボード
notes: >-
thelook EC の売上モニタリング。確定売上(Cancelled / Returned を除く net_revenue)を
基準に、期間・カテゴリ・地域で絞り込む。集計元は dbt の marts モデル。
source: analytics
variables:
period:
input: daterange
label: 期間
notes: 注文日(fct_order_items.order_date)の範囲。既定は直近12か月。
default: ['2025-10-01', '2026-09-19']
categories:
input: multiselect
label: 分類
notes: >-
department / category の結合ラベル。空 = 全カテゴリ。
category 単独だと Men / Women で同名が衝突するため結合ラベルを使う。
default: []
options:
query: category_options
column: department_category
countries:
input: multiselect
label: 地域
notes: 顧客の所在国。空 = 全地域。配送センターの所在地ではない。
default: []
options:
query: country_options
column: country
queries:
category_options:
notes: カテゴリフィルターの選択肢。
sql: |
SELECT DISTINCT department_category
FROM {{ ref('agg_sales_daily_by_category') }}
ORDER BY 1
country_options:
notes: 地域フィルターの選択肢。
sql: |
SELECT DISTINCT country
FROM {{ ref('agg_sales_daily_by_region') }}
ORDER BY 1
kpi_totals:
notes: >-
ヘッドラインKPI。確定売上・注文数・平均単価を1行で返す。
Cancelled / Returned は net_revenue / is_net_sale で除外済み。
sql: |
SELECT
SUM(net_revenue) AS net_revenue,
COUNT(DISTINCT IF(is_net_sale, order_id, NULL)) AS net_orders,
SAFE_DIVIDE(SUM(net_revenue),
COUNT(DISTINCT IF(is_net_sale, order_id, NULL))) AS net_aov
FROM {{ ref('fct_order_items') }}
WHERE {{ filter_date_range('order_date', period) }}
AND {{ filter('department_category', categories) }}
AND {{ filter('country', countries) }}
trend_monthly:
notes: 月次の確定売上推移。既定期間(直近12か月)で12点になる。
sql: |
SELECT
DATE_TRUNC(order_date, MONTH) AS month,
SUM(net_revenue) AS net_revenue
FROM {{ ref('fct_order_items') }}
WHERE {{ filter_date_range('order_date', period) }}
AND {{ filter('department_category', categories) }}
AND {{ filter('country', countries) }}
GROUP BY month
ORDER BY month
by_category:
notes: カテゴリ別の確定売上。上位10件に絞る(全36件は棒グラフに多すぎる)。
sql: |
SELECT
department_category,
SUM(net_revenue) AS net_revenue
FROM {{ ref('fct_order_items') }}
WHERE {{ filter_date_range('order_date', period) }}
AND {{ filter('department_category', categories) }}
AND {{ filter('country', countries) }}
GROUP BY department_category
ORDER BY net_revenue DESC
LIMIT 10
by_region:
notes: 国別の確定売上。顧客の所在国ベース。全14か国。
sql: |
SELECT
country,
SUM(net_revenue) AS net_revenue
FROM {{ ref('fct_order_items') }}
WHERE {{ filter_date_range('order_date', period) }}
AND {{ filter('department_category', categories) }}
AND {{ filter('country', countries) }}
GROUP BY country
ORDER BY net_revenue DESC
detail_rows:
notes: >-
直近の注文明細。確定売上のみ。1行 = 商品1個。
チャートでは見えない個別取引を確認するためのドリルダウン用。
sql: |
SELECT
order_date,
department_category,
country,
brand,
net_revenue,
net_gross_profit
FROM {{ ref('fct_order_items') }}
WHERE {{ filter_date_range('order_date', period) }}
AND {{ filter('department_category', categories) }}
AND {{ filter('country', countries) }}
AND is_net_sale
ORDER BY order_date DESC, net_revenue DESC
LIMIT 15
charts:
kpi_revenue:
query: kpi_totals
type: kpi
label: 売上
notes: 確定売上(Cancelled / Returned 除外)。
value: net_revenue
style:
value:
format: currency
kpi_orders:
query: kpi_totals
type: kpi
label: 注文数
notes: 確定売上の注文数(重複排除済み)。
value: net_orders
style:
value:
format: integer
kpi_aov:
query: kpi_totals
type: kpi
label: 平均単価
notes: 確定売上 ÷ 確定注文数。
value: net_aov
style:
value:
format: currency_whole
trend_chart:
query: trend_monthly
type: line
title: 月次売上
notes: 売上トレンド。ダッシュボードの主軸。
x: month
y: net_revenue
height: 300
style:
number_format: currency
time_format: "%Y-%m"
category_chart:
query: by_category
type: bar
title: カテゴリ別 上位10
notes: どのカテゴリが売上を稼いでいるか。
x: department_category
y: net_revenue
height: 300
style:
number_format: currency
region_chart:
query: by_region
type: bar
title: 国別売上
notes: どの国が売上を稼いでいるか。
x: country
y: net_revenue
height: 300
style:
number_format: currency
detail_table:
query: detail_rows
type: table
title: 直近の明細
notes: 直近15件の注文明細。
style:
columns:
order_date:
label: 日付
department_category:
label: カテゴリ
country:
label: 国
brand:
label: ブランド
net_revenue:
label: 売上
format: currency_whole
align: right
net_gross_profit:
label: 粗利
format: currency_whole
align: right
rows:
- cols: [kpi_revenue, kpi_orders, kpi_aov]
- trend_chart
- cols: [category_chart, region_chart]
- detail_table
グラフを追加してみる
棒グラフ・折れ線・表だけでは表現の幅が分からないので、他の種別も足してもらいました。
— プロンプト
charts/sales.ymlはそのまま残し、新しくcharts/explore.ymlを作って、dbt Chartsで使えるチャート種別をひと通り見せるボードにしてください。先にdct docs chartsを読み、必要なら marts モデルを追加してください。・ドーナツ:商品カテゴリ別の売上構成比
・散布図:商品の価格と販売数量の関係(カテゴリで色分け)
・ヒストグラム:注文単価の分布
・ヒートマップ:曜日×時間帯の注文数
・地図:point_mapかbubble_mapで地域ごとの売上
・二軸コンボ:layers:で月次売上(棒)と平均注文単価(折れ線)を重ね、折れ線はaxis_y.position: right
・スモールマルチプル:multiples:で流入元ごとの売上推移を並べる
・callout:ボード冒頭に、対象期間とデータソースの注記フィルターは同じ期間・カテゴリ・地域を付け、各クエリのWHERE句に直接書いてください。書き終えたら
dct validate --strictとdct render --format pngで確認し、崩れを直してください。
同様にブラウザで確認します。

指示した通りの構成になりました。ここまでYAML1枚の追加で、差分はgit diffで読めます。
title: チャート種別カタログ
notes: >-
dbt charts で使えるチャート種別を thelook の marts モデルで一通り見せる探索用ボード。
売上はすべて確定売上(net_revenue / Cancelled・Returned 除外)。
フィルターは sales.yml と同じ 期間・分類・地域。
凡例と軸のタイトルは列名から作られるため、表示用の列は日本語別名を付けている。
source: analytics
variables:
period:
input: daterange
label: 期間
notes: 注文日(fct_order_items.order_date)の範囲。既定は直近12か月。
default: ['2025-10-01', '2026-09-19']
categories:
input: multiselect
label: 分類
notes: department / category の結合ラベル。空 = 全分類。
default: []
options:
query: category_options
column: department_category
countries:
input: multiselect
label: 地域
notes: 顧客の所在国。空 = 全地域。
default: []
options:
query: country_options
column: country
queries:
category_options:
notes: 分類フィルターの選択肢。
sql: |
SELECT DISTINCT department_category
FROM {{ ref('agg_sales_daily_by_category') }}
ORDER BY 1
country_options:
notes: 地域フィルターの選択肢。
sql: |
SELECT DISTINCT country
FROM {{ ref('agg_sales_daily_by_region') }}
ORDER BY 1
mix_by_category:
notes: >-
ドーナツ用。売上上位5分類の構成比。全36分類はどれも小さく均等に分散しており、
「その他」に畳むと約7割を占めて読めなくなるため上位5件に絞る
(スコープはタイトルで明示)。6件以上はスライスの角度が比較できず警告も出る。
sql: |
SELECT
department_category AS `分類`,
SUM(net_revenue) AS `売上`
FROM {{ ref('fct_order_items') }}
WHERE {{ filter_date_range('order_date', period) }}
AND {{ filter('department_category', categories) }}
AND {{ filter('country', countries) }}
GROUP BY `分類`
ORDER BY `売上` DESC
LIMIT 5
order_value_dist:
notes: >-
ヒストグラム用。注文1件あたりの確定売上。1行 = 1注文。
最大 1,287 ドルまで裾を引き、全件を渡すとビンが粗くなって
最初の1本しか見えないため 500 ドル以下(全体の約99%)に絞る。
sql: |
SELECT order_value AS `注文単価`
FROM (
SELECT
order_id,
SUM(net_revenue) AS order_value
FROM {{ ref('fct_order_items') }}
WHERE {{ filter_date_range('order_date', period) }}
AND {{ filter('department_category', categories) }}
AND {{ filter('country', countries) }}
AND is_net_sale
GROUP BY order_id
)
WHERE order_value -
散布図用。1行 = 1商品。x=定価, y=販売数量。売上上位6分類に絞る
(全36分類を色分けすると凡例が読めない)。
sql: |
WITH top_categories AS (
SELECT department_category
FROM {{ ref('fct_order_items') }}
WHERE {{ filter_date_range('order_date', period) }}
AND {{ filter('department_category', categories) }}
AND {{ filter('country', countries) }}
GROUP BY department_category
ORDER BY SUM(net_revenue) DESC
LIMIT 6
)
SELECT
product_id,
ANY_VALUE(department_category) AS `分類`,
ANY_VALUE(retail_price) AS `定価`,
COUNTIF(is_net_sale) AS `数量`
FROM {{ ref('fct_order_items') }}
WHERE {{ filter_date_range('order_date', period) }}
AND {{ filter('department_category', categories) }}
AND {{ filter('country', countries) }}
AND department_category IN (SELECT department_category FROM top_categories)
GROUP BY product_id
HAVING `数量` > 0
orders_by_dow_hour:
notes: >-
ヒートマップ用。曜日×時間帯の注文数。1注文が複数明細を持つため
COUNT(DISTINCT order_id) で数える。7×24 = 最大168セル。
曜日ラベルは並び順を保つため ISO 曜日番号を前置する。
sql: |
SELECT
-- 軸は文字列の昇順に並ぶため、曜日順になるよう ISO 曜日番号を頭に付ける
-- (%u は月曜=1, 日曜=7)。
CASE FORMAT_DATE('%u', order_date)
WHEN '1' THEN '1 月' WHEN '2' THEN '2 火' WHEN '3' THEN '3 水'
WHEN '4' THEN '4 木' WHEN '5' THEN '5 金' WHEN '6' THEN '6 土'
ELSE '7 日'
END AS `曜日`,
EXTRACT(HOUR FROM ordered_at) AS `時`,
COUNT(DISTINCT IF(is_net_sale, order_id, NULL)) AS `注文数`
FROM {{ ref('fct_order_items') }}
WHERE {{ filter_date_range('order_date', period) }}
AND {{ filter('department_category', categories) }}
AND {{ filter('country', countries) }}
GROUP BY `曜日`, `時`
sales_by_geo:
notes: >-
地図用。国ごとの売上と、その国の購入者の緯度経度の重心。
配送センターではなく顧客の所在地ベース。
sql: |
SELECT
country,
AVG(user_latitude) AS lat,
AVG(user_longitude) AS lng,
SUM(net_revenue) AS `売上`
FROM {{ ref('fct_order_items') }}
WHERE {{ filter_date_range('order_date', period) }}
AND {{ filter('department_category', categories) }}
AND {{ filter('country', countries) }}
GROUP BY country
monthly_revenue_aov:
notes: >-
二軸コンボ用。月次の売上(棒)と平均注文単価(折れ線)。
桁が3桁違うため単価を右軸に分ける。
sql: |
SELECT
DATE_TRUNC(order_date, MONTH) AS `月`,
SUM(net_revenue) AS `売上`,
SAFE_DIVIDE(SUM(net_revenue),
COUNT(DISTINCT IF(is_net_sale, order_id, NULL))) AS `単価`
FROM {{ ref('fct_order_items') }}
WHERE {{ filter_date_range('order_date', period) }}
AND {{ filter('department_category', categories) }}
AND {{ filter('country', countries) }}
GROUP BY `月`
ORDER BY `月`
monthly_by_source:
notes: >-
スモールマルチプル用。流入元×月の売上推移。流入元は users 由来の5値
(events.traffic_source とは別系統)。
sql: |
SELECT
DATE_TRUNC(order_date, MONTH) AS `月`,
traffic_source AS `流入元`,
SUM(net_revenue) AS `売上`
FROM {{ ref('fct_order_items') }}
WHERE {{ filter_date_range('order_date', period) }}
AND {{ filter('department_category', categories) }}
AND {{ filter('country', countries) }}
GROUP BY `月`, `流入元`
ORDER BY `月`
charts:
intro_note:
type: callout
message: >-
対象期間・分類・地域は上部フィルター連動(既定は直近12か月)
/ 出典: BigQuery 公開データセット thelook ecommerce
/ 集計: dbt marts の売上ファクト
/ 金額は確定売上のみ(Cancelled・Returned 除外)
style:
tone: info
mix_donut:
query: mix_by_category
type: donut
title: 上位5分類の構成比
notes: 売上上位5分類の内訳。全分類ではない点はタイトルで明示。
theta: 売上
color: 分類
height: 320
total:
label: 上位5計
style:
total:
value:
format: currency
value_hist:
query: order_value_dist
type: histogram
title: 注文単価の分布(〜$500)
notes: 注文単価のばらつき。右に長い裾を持つ。
x: 注文単価
y_label: 件数
height: 320
price_qty_scatter:
query: product_price_qty
type: scatter
title: 価格と数量(上位6分類)
notes: 定価が高い商品ほど売れる数は少ないか。
x: 定価
y: 数量
color: 分類
height: 320
y_label: 数量
style:
axis_y:
position: left
axis_x:
labels:
format: currency_whole
legend:
position: bottom
columns: 2
dow_hour_heatmap:
query: orders_by_dow_hour
type: heatmap
title: 曜日×時間の注文数
notes: 注文が集中する時間帯。
x: 時
y: 曜日
color: 注文数
height: 320
revenue_aov_combo:
query: monthly_revenue_aov
type: bar
title: 月次売上と単価
notes: 売上(棒・左軸)と平均注文単価(折れ線・右軸)の二軸コンボ。
x: 月
y: 売上
height: 320
style:
number_format: currency
time_format: "%y/%m"
layers:
- type: line
y: 単価
label: 単価
axis_y:
position: right
title: 単価
geo_map:
query: sales_by_geo
type: bubble_map
title: 国別売上(地図)
notes: 購入者の所在地重心に売上規模をバブルで重ねる。
latitude: lat
longitude: lng
size: 売上
height: 320
basemap:
source: world-countries
source_multiples:
query: monthly_by_source
type: line
title: 流入元別の推移
notes: 流入元ごとに売上推移を並べて比較する。
x: 月
y: 売上
multiples:
columns: 流入元
height: 260
style:
number_format: currency
time_format: "%y/%m"
rows:
- intro_note
- cols: [mix_donut, value_hist]
- cols: [price_qty_scatter, dow_hour_heatmap]
- cols: [revenue_aov_combo, geo_map]
- source_multiples
使えるチャートは16種類です。bar・line・area・scatter・pie(donut)・kpi・table・histogram・heatmap・geoshape・map・point_map・bubble_map・spark_bar・callout といった顔ぶれで、積み上げやグルーピング、100%積み上げはstyle.stackで表現します。一方、ファネル、ウォーターフォール、ツリーマップ、サンキー、ゲージ、ガントはありません。独自のチャートを定義することもできず、任意のVega-Lite記述を受け付けない仕様です。
つまずいた点
v0.7.1時点で踏んだものです。1.0までにYAMLの構文自体も変わる予定なので、現時点のメモとして読んでください。
フィルターを変えても数値が変わらない
最初に作ったボードで、フィルターが効いてい場合がありました。原因はdct serveのクエリ結果のキャッシュと思われます。共通のクエリを{{ queries.base }}の形で他のクエリに組み込んでいると、キャッシュの判定にフィルターの値が含まれず、最初の結果が使い回されるようです。
各クエリのWHERE句にフィルターを直接書く形にすれば解消します。
タブや折りたたみを使うとフィルターが壊れる
tabs:やdetails:の切り替えリンクを作るとき、複数選択や日付範囲の値がURLに正しい形式で入りません。日付範囲は500エラーになり、複数選択はデータが0件になります。1ページ構成にするか、単一選択の変数で代用するのが無難です。
日本語まわり
フィルターのラベルの幅計算が日本語の表示幅とずれるらしく、「カテゴリ」程度の長さでも隣の入力欄と文字が重なりました。ラベルを短くする、初期値を入れずに「すべて」と表示させる、といった調整で回避しています。
他のコードベースのBIとの比較
YAMLでダッシュボードを管理できるツールは他にもあります。Lightdashは、指標・チャート・ダッシュボードをYAMLで書き出してGit管理でき、UIで作ったものをlightdash downloadで取り出す双方向の運用です。
dbt ChartsとLightdashの一番の違いは、YAMLの位置づけです。LightdashのYAMLはUIで作った成果物の書き出しである一方、dbt ChartsではYAMLが唯一の正本で、人やAIが直接書く前提の簡潔な構文になっています。
ただし、Lightdashが持つセマンティックレイヤーによる指標の統制、業務担当者が自分でディメンションを選んで掘り下げるセルフサービス分析、フィルター適用済みダッシュボードの定期配信といった機能は、現時点のdbt Chartsにはありません。dbt Semantic Layerのメトリクスを名前で呼べるようにする構想はありますが、まだ計画段階です。
使ってみた感想
TableauのようなBIと比べると、表現の制限はかなり多いです。チャートの種類は絞られ、「この見せ方にしたい」という要求が細かくなるほど手が止まります。Streamlitを触っているときのあと一歩の調整ができない歯痒さに近い感覚がありました。
一方で、用途を絞ると評価が変わります。dbtプロジェクトの開発中や運用中に、作ったモデルの数値をその場で目視確認するためのダッシュボードとしては、かなり具合が良いです。BIツールを開いてデータソースを登録して……という工程に出ていかずに、dbtの作業ディレクトリの中だけで完結します。モデルを直してdbt build、そのままdct serveで数値を見る、という往復が同じリポジトリの中で回るのは快適でした。
「BIツールの代替」ではなく、「dbt開発の確認用ダッシュボード」と捉えると、現時点でも十分に使えると感じます。AIに書かせやすい構文であることも、この用途と相性が良いです。
公開されたばかりで、構文も含めてこれから変わっていくツールです。セマンティックレイヤーとの連携や表現の拡充が進めば、BIツールとしての用途にも耐えるものになるかもしれません。期待しつつ、アップデートを追っていきます。





