民主化を「全員に を書かせる」と捉えるのは間違いです。実際の問いの 8 割はパターン化できる。頻出パターンをテンプレ化し、パラメータだけ変える仕組みを用意することで、自由度を奪わずに再現性を上げることができます。
テンプレート化が効くシーン
| パターン | 例 |
|---|---|
| 期間 × 軸別の集計 | 「2024年Q3」の「カテゴリ別」売上 |
| Top N | 「先月の」「離反率の高い」上位10セグメント |
| 「2024年4月入会」顧客の「月次離反率」 | |
| 「サインアップ → 初回購入 → 2回目購入」の通過率 | |
| A/B 比較 | 「機能Aあり/なし」での「3日後の継続率」 |
Pattern 1: SQL の文字列テンプレート(最簡)
from jinja2 import Template
template = Template("""SELECT DATE_TRUNC({{ date_column }}, {{ granularity }}) AS period, {% if dimension %}{{ dimension }},{% endif %} COUNT(*) AS cnt, SUM(amount_jpy) AS revenueFROM {{ table }}WHERE _PARTITIONTIME BETWEEN '{{ start_date }}' AND '{{ end_date }}' {% if filters %}{% for f in filters %}AND {{ f }}{% endfor %}{% endif %}GROUP BY 1{% if dimension %}, 2{% endif %}ORDER BY 1LIMIT 1000;""")
sql = template.render( table="proj.dwh.orders", date_column="created_at", granularity="month", dimension="category", start_date="2027-01-01", end_date="2027-12-31", filters=["region = 'east'"],)print(sql)ユーザ入力を直接 Jinja に渡すのは危険。ホワイトリスト式の選択肢(ドロップダウン)で渡すか、列挙型でバリデーションすること。テンプレに渡る値は事前に検証する設計が必須。
① 既存ツールに乗せたい: Slack Bot (EP.04) や社内 ChatBot 内で SQL を組み立てる時。② 数十パターン程度の固定テンプレ: パターン数が爆発しない見込み。③ 最小依存で素早く始めたい: ツール導入が間に合わない、PoC 段階。❌ 向かない: アナリスト/業務担当が GUI でいじりたい、テンプレ数が 100+ になる、複数の BI クライアントから参照される。
Pattern 2: Looker Explore(ビジネス向き)
Looker の Explore はテンプレートそのもの。LookML で定義した dimensions / measures をユーザがGUI で組合せ、SQL は生成される。「テンプレ + 」の鉄板パターン。
view: orders { sql_table_name: `proj.dwh.orders` ;;
dimension: order_id { primary_key: yes } dimension_group: created { type: time timeframes: [date, week, month, quarter, year] sql: ${TABLE}.created_at ;; } dimension: region { type: string sql: ${TABLE}.region ;; } dimension: category { type: string sql: ${TABLE}.category ;; }
measure: count { type: count } measure: revenue { type: sum sql: ${TABLE}.amount_jpy ;; value_format_name: jpy_0 } measure: aov { type: number sql: ${revenue} / NULLIF(${count}, 0) ;; }}
explore: orders { description: "注文データ。期間 / 地域 / カテゴリで自由に切れます"}① 数百ダッシュ規模で運用: アナリスト・業務担当が日常的に GUI で切る。② 部署横断の利用: マーケ・営業・経営が同じ Explore を参照。③ 経営層の予算がある: Looker / 等 BI 製品ライセンスを既に取得済み or 取れる。④ の継続観測: 月次・週次の定型ダッシュ需要が中心。❌ 向かない: BI 製品ライセンスがない / 取れない、コードファーストで運用したい、業務固有の複雑な操作(シミュレーション等)がある。
Pattern 3: dbt metrics(指標の正本管理)
指標の定義を dbt の `metrics:` に書くと、全クライアント(Looker / Streamlit / SQL)から同一定義で参照できる。「営業の言う売上」と「経理の言う売上」が違う問題を構造的に防ぐ。
version: 2metrics: - name: revenue label: "売上 (JPY, 税込)" model: ref('orders') description: "確定済み注文の合計金額。返金は減算済み" type: simple type_params: measure: name: amount_jpy agg: sum filter: "{{ Dimension('orders__status') }} = 'completed'"
- name: monthly_active_customers label: "MAC" type: simple type_params: measure: name: customer_id agg: count_distinct time_granularity: month① 部署で数字が食い違う問題が深刻: 「営業の売上 vs 経理の売上」が違って報告会で揉める。② 複数 BI ツールを併用: Looker と Tableau と Slack Bot から同じ metric を参照したい。③ を既に運用: dbt プロジェクトがある(無いと導入コストが高い)。④ 中〜大規模組織: 数十人以上が同じ指標を見る。❌ 向かない: dbt 未導入、metric 数が 5 個以下で十分、BI 1 つだけで完結する小規模。詳細は dbt ハンドブック EP.14 Semantic Layer。
Pattern 4: Streamlit でテンプレ + UI
import streamlit as stimport pandas as pdfrom datetime import datefrom google.cloud import bigquery
st.title("📊 期間別売上テンプレート")
# 入力start = st.date_input("開始日", date(2027, 1, 1))end = st.date_input("終了日", date(2027, 12, 31))granularity = st.selectbox("粒度", ["day", "week", "month"])region = st.selectbox("地域", ["全国", "east", "west", "central"])
# テンプレ展開where_region = "" if region == "全国" else f"AND region = '{region}'"sql = f"""SELECT DATE_TRUNC(created_at, {granularity.upper()}) AS period, SUM(amount_jpy) AS revenueFROM proj.dwh.ordersWHERE _PARTITIONTIME BETWEEN '{start}' AND '{end}' {where_region}GROUP BY 1 ORDER BY 1"""
if st.button("実行"): bq = bigquery.Client() df = bq.query(sql).to_dataframe() st.line_chart(df.set_index("period")["revenue"]) st.dataframe(df)① 業務固有のフローが必要: 「シミュレーション」「複数操作の組合せ」「結果に応じた次操作」など、Looker の Explore では作りにくい体験。② Python エンジニアが内製で組める: SQL だけでは表現しきれない計算(pandas/numpy 必要)が混ざる。③ 1 ツールに 1 ユースケースで深く: 「価格シミュレータ」「在庫発注計画」など、対象業務が明確。④ 認証付きで社内限定運用: Streamlit Community Cloud は SSO 弱め、Cloud Run + IAP / Streamlit in などの本番構成を組める前提。❌ 向かない: 「ダッシュ並べたい」だけ(Looker の方が早い)、Python エンジニアがいない、保守を業務担当に渡したい。
4 パターンの早見表
| 観点 | P1: SQL文字列 | P2: Looker | P3: dbt metrics | P4: Streamlit |
|---|---|---|---|---|
| 主な利用者 | Bot 経由の業務担当 | アナリスト・業務担当 | アナリスト + BI クライアント | 業務担当(GUI 操作) |
| 初期コスト | 低(ライブラリのみ) | 中〜高(Looker ライセンス) | 中(dbt セットアップ) | 中(Python 環境 + ホスティング) |
| 運用コスト | 低 | 高(テンプレ管理) | 低( で集中管理) | 中(コード保守) |
| 指標統一 | ❌(テンプレごと) | △(LookML 内) | ✅(最強) | ❌(コードごと) |
| 業務複雑度 | 単純集計 | ダッシュ系 | 指標定義 | 複雑な操作・シミュレーション |
| 規模 | 小〜中 | 中〜大 | 中〜大 | ピンポイント |
中規模組織 (200〜1000 人) には: dbt metrics で指標正本 + Looker で日常ダッシュ + Streamlit で業務固有フロー + Slack Bot で問合せ の 4 段重ね。スタートアップ (50 人未満) なら: + Slack Bot 軽量 から。dbt 未導入なら、まずそこから (EP.07)。
テンプレ運用の落とし穴
1. テンプレが増殖して結局カオス
Looker のダッシュボードが 1000 個。テンプレ自体に所有者・利用ログ・を持たせる。3 ヶ月利用ゼロのテンプレは アーカイブ。
2. テンプレで満たせない問いが「アナリスト依頼」化
テンプレ既存のものから10%でも外れると、結局アナリスト依頼に。「テンプレ + ちょい追加」の組合せを許す(Looker の `Filters` / Streamlit の入力欄拡張)。
3. 古い指標定義のまま放置
事業の変化で指標の定義も変わる。dbt metrics で正本管理 + Glossary(EP.07-08)の整合性を保つ。
次の話
EP.10 では、誰が何を見たかを追う『監査ログと利用ログ』。事故対応・コンプライアンス・継続改善の基盤。
この記事の感想を教えてください
あなたの 1 クリックで、本当にこの記事は更新されます。「もっと詳しく」「続編希望」が一定数集まった記事は、 ふくふくが 実際に内容を拡充したり続編記事を公開 します。 送信したリアクションはお使いのブラウザに記録され、再カウントされません。