0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

rex0220 kSQL アクションプラグイン - ⑤ 事例編(10 万件を集計して Dashboard Pro で見る)

0
Last updated at Posted at 2026-11-01

「rex0220 kSQL アクションプラグイン」の実践編です。

売上 10 年分 10 万件を年別・都道府県別に集計して、kSQL Dashboard Pro で見る、という事例をひと通りやります。開発環境で実際に作って測った数字をそのまま載せます。

シリーズ: 概要 / ① 詳細画面 / ② 一覧 / ③ 集計 / ④ 運用 / ⑤ 事例(この記事) / ⑥ イベント / ⑦ オーサリング / ⑧ 請求データ / ⑨ 締めの画面 / ⑩ どこに出すか / ⑪ 多言語 / ⑫ オーサリング改善

ダッシュボードが作れなくなる日

Dashboard Pro の取得件数の上限は、ペインごとに 500〜50,000 件です(既定は 10,000 件)。売上アプリにそのままダッシュボードを置くと、こうなります。

見たいもの 読む件数 Dashboard Pro 単体
今年の都道府県別 約 9,400 件 既定(10,000)でぎりぎり足りる
5 年分の推移 約 4.7 万件 上限を 50,000 に上げれば届く
10 年分の推移 約 9.4 万件 上限を上げても届かない

1 年だけ見るうちは何も困りません。年が増えて「10 年の推移を 1 枚で見たい」と言われた日に、上限に当たります。

件数より先に効くのは API

そしてもう 1 つ、件数の上限より先に効いてくるものがあります。ダッシュボードは複数の人が何回も開くので、そのたびに kintone の API を使います(約 500 件 = 1 リクエスト)。

今回のダッシュボード(4 ペイン)を開いたときの通信を実際に数えました。

回数
records.json(レコードの取得) 3 回
app/form/fields.json(項目の定義) 1 回
1 回開くと合計 4 回

ペインは 4 つなのに取得は 3 回です。同じ問い合わせになるペインは 1 本にまとまります(棒と横棒は、どちらも「470 行の 年・都道府県・売上」を読むので 1 回で済んでいる)。

これを、集計せずに売上アプリを直接見る場合と比べます。問い合わせの数は同じ 3 本なので、1 本あたり「件数 ÷ 500」回になります。

ダッシュボードが見るもの 1 回開くと 10 人が 1 日 10 回開くと
10 年分 9.4 万件を直接 そもそも上限で不可 —
1 年分 9,400 件を直接 約 57 回(19 × 3 本) 約 5,700 回
集計した 470 行 4 回(実測) 400 回

kintone の 1 アプリ 1 日のリクエスト数には上限があります。見るだけで 1 日 5,700 回使う画面は、それだけで窮屈です。

Dashboard Pro 側にも手当てはあります。表示中のタブだけ集計する、一度開いたタブは往復しても再実行しない、折りたたみ中は止まる、など。上の数字は「画面を開いた回数」で数えたもので、同じ画面を眺め続ける分には増えません。

考え方:上限に当てない

ここで「上限を 50,000 まで上げる」方向に行くと、余裕のない設計になります。データは増え続けるので、いつかまた当たります。

やることは逆で、ダッシュボードに読ませる件数そのものを減らします。

売上 94,000 件  --(kSQL アクションで事前集計)-->  集計 470 行  --> ダッシュボード

10 年 × 47 都道府県 = 470 行。これならどのペインも一瞬で、470 行は 500 件に収まるので取得は問い合わせ 1 本につき 1 回。4 ペインのダッシュボード全体でも 4 回(上の実測)です。

集計アプリの一覧に並ぶ、アクションのボタンとダッシュボード

アプリは 2 つ

アプリ 項目
売上 売上日 / 年(数値)/ 都道府県 / 金額 / 商品区分。約 9.4 万件
年別都道府県別集計 集計キー(文字列1行・値の重複を禁止)/ 年 / 都道府県 / 件数 / 売上 / 集計日時

売上アプリ(94,047 件)

ここで 2 つ、つまずきやすいところがあります。

複合キーは「連結した文字列」で作る

集計の単位は「年 × 都道府県」ですが、kintone に複合キーはありません。UPSERT のキーには値の重複を禁止した項目が 1 つ要るので、2026-東京都 のように連結した文字列の項目を作って、そこに重複禁止を付けます。

キーには集計の単位をすべて入れます。あとで月単位に細かくするなら、キーも 2026-06-東京都 のように「年月 × 都道府県」に変えます。2026-東京都 のままだと、6 月を集計した結果がその年の行を上書きしてしまいます。

集計の軸は、元のアプリに持たせる

売上日から年を取り出して絞ることもできますが、年を数値の項目として売上アプリに持たせるほうが速いです。WHERE 年 = @year なら kintone の絞り込みがそのまま効きます。

アクションは 2 本だけ

集計アプリの一覧パネルにボタンを 2 つ置きます。

一覧パネルの 2 つのボタン

読む 書く 使いどころ
この年を集計し直す(年を選ぶ) 約 9,400 件 47 行 過去の年を直すとき・導入のとき
今年を集計し直す(ボタン 1 つ) 約 9,400 件 47 行 日々これを押す

SQL は 2 本とも同じです。

-- @ksql dialect: 1
DECLARE @year = '';
DECLARE @now = '';

UPSERT INTO LAPP_集計 (集計キー, 年, 都道府県, 件数, 売上, 集計日時)
SELECT CONCAT(@year, '-', 都道府県) AS 集計キー,
       @year AS 年,
       都道府県,
       COUNT(*) AS 件数,
       SUM(金額) AS 売上,
       @now AS 集計日時
  FROM LAPP_売上
 WHERE 年 = @year
 GROUP BY 都道府県
 ON DUPLICATE (集計キー);

違うのは @year の入れ方だけです。

  • 「この年を集計し直す」は入力項目(年の選択肢を 10 年分)
  • 「今年を集計し直す」は計算式 DATE_FORMAT("TODAY", "YYYY")

年を選ぶ入力

SQL で引っかかったところ

  • NOW() は SELECT の列には書けません(UPDATE … SET 集計日時 = NOW() なら書けます)。1 文で済ませたいので、集計日時も計算式のパラメーターにしました(DATE_FORMAT("TODAY", "YYYY-MM-DDTHH:mm:ssZ"))
  • SELECT の列にパラメーターを置くときは AS の別名が要ります(@year AS 年)
  • CONCAT(@year, '-', 都道府県) は通ります

消えた都道府県を 0 にする

上の UPSERT には GROUP BY があるので、元が 0 件のグループは 1 行も書きません。ある年から都道府県が丸ごと消えると、集計アプリには前回の値が残ったままになり、10 年の合計が実際より多く出ます。

消してから入れ直す(DELETE FROM LAPP_集計 WHERE 年 = @year; → INSERT … SELECT)手もありますが、2 文なので消したあとで失敗するとその年が空になります。消さずに済ませるなら、0 の行を UNION ALL で足してから集計します。

-- @ksql dialect: 1
DECLARE @year = '';
DECLARE @now = '';

CREATE TEMP TABLE #t AS
SELECT 都道府県, COUNT(*) AS 件数, SUM(金額) AS 売上
  FROM LAPP_売上 WHERE 年 = @year GROUP BY 都道府県
UNION ALL
SELECT 都道府県, 0 AS 件数, 0 AS 売上
  FROM LAPP_集計 WHERE 年 = @year;

UPSERT INTO LAPP_集計 (集計キー, 年, 都道府県, 件数, 売上, 集計日時)
SELECT CONCAT(@year, '-', 都道府県) AS 集計キー, @year AS 年, 都道府県,
       SUM(件数) AS 件数, SUM(売上) AS 売上, @now AS 集計日時
  FROM #t GROUP BY 都道府県
 ON DUPLICATE (集計キー);

下側は、前回書いた行から作った0 の控えです。売上が残っている都道府県は上側の値がそのまま通り(0 を足しても変わらない)、消えた都道府県は下側だけが残って 0 で更新されます。消す文が無いので、途中で失敗しても空の年にはなりません。

試しに、売上が 1 件も無い都道府県の行を集計アプリに 1 つ置いてから動かしてみました。確認の画面は「レコードを 48 件 更新します」(47 都道府県 + その 1 件)になり、7.0 秒で完了。売上が残っている都道府県の値はそのままで、置いた 1 件だけが 0 件 / 0 円になりました。

書くときに気をつけるところ:

  • 上側は COUNT(*)、まとめるときは SUM(件数) です。#t を COUNT(*) で数えると 0 の行まで数えてしまいます
  • FROM (SELECT … UNION ALL …) の入れ子(導出表)は書けません。WITH は書けますが、後ろに続けられるのは SELECT だけで、UPSERT の直前には置けません。UNION ALL は一時テーブルに受ける形にします(CREATE TEMP TABLE #t AS WITH … SELECT … UNION ALL … も通ります)
  • 一時テーブルの上限は、貯まった行数ではなく読んだ行数で見ます。1 年 9,400 件なら 9,400 件として数えるので、既定(10,000)で足りますが、読み取りの上限と同じ余裕しかありません
  • 0 の控えを読むぶん、API が 1 回増えます(23 回 → 24 回。実行ログの実測)

連続した軸(日・月・年)なら、系列を作って左結合する

都道府県のような飛び飛びのキーには上の形(0 の控え)が要りますが、日・月・年のように連続している軸なら、軸そのものを GENERATE_SERIES で作って LEFT JOIN するほうが素直です。前回書いた行に頼りません。

鳥取県の 2026 年 11 月で試します。この月に売上があるのは 3 日だけ(レコードは 4 件)です。

WITH 日付系列 AS (GENERATE_SERIES('2026-11-01', '2026-11-30') AS 日付),
     日別 AS (SELECT 売上日, SUM(金額) AS 合計
                FROM LAPP_売上
               WHERE 都道府県 = '鳥取県' AND 売上日 >= '2026-11-01' AND 売上日 <= '2026-11-30'
               GROUP BY 売上日)
SELECT s.日付, CASE WHEN d.合計 = '' THEN 0 ELSE d.合計 END AS 合計
  FROM 日付系列 AS s
  LEFT JOIN 日別 AS d ON s.日付 = d.売上日
 ORDER BY s.日付;

4 件のレコードから 30 行が出ます。

2026-11-01        0
2026-11-02   152484
2026-11-03        0   ← 11-09 まで 0 が並ぶ
2026-11-10   112119
2026-11-11        0
2026-11-12   269483   ← この日は 2 件あったので合算
2026-11-13        0   ← 11-30 まで 0 が並ぶ

この SQL は Dashboard Pro のペインにもそのまま貼れます(実測: 30 行 / 372 ms)。棒グラフにすると、売れなかった日も軸に並ぶのでグラフが途切れません。

鳥取県の 11 月(日別。売上が無い日も 0)

書くときに気をつけるところ:

  • GENERATE_SERIES は WITH の中(CTE の本体)に書きます。SELECT GENERATE_SERIES(…) とは書けません
  • 刻みは第 3 引数です('1 month' で月初が並び、数値なら GENERATE_SERIES(1, 10, 2) で 1, 3, 5, 7, 9)
  • LEFT JOIN で欠けた側は空文字なので、CASE WHEN d.合計 = '' THEN 0 … で 0 にします
  • 文字列はシングルクォートです("鳥取県" と書くと KSQL1201 予期しない文字 になります)

導入のときも、分割すれば特別なことは要らない

10 年分をまとめて読む必要はありません。「この年を集計し直す」を年を変えて 10 回押すだけです。

1 回 9,400 件なので、kSQL アクション側の読み取りの上限も既定(10,000)のままで足ります。設定をいじらずに済むのは大きくて、「データが増えたら上限も上げる」という運用を抱え込まずに済みます。

実測

開発環境で測った数字です。

値
読んだ件数 1 年 9,400 件
書いた件数 47 行
かかった時間 6〜8 秒
API 23 回(読み 19 + 書き 1 + ログ 3)
10 年分(ボタンを 10 回) 470 行・230 回・1 分少々

10 回とも API は同じ 23 回で、ぶれたのは時間だけでした。

ダッシュボード側はこうです。

ペイン 表示 結果
10 年の売上合計 KPI カード 1 行 / 267 ms
年別の売上 棒 10 行 / 326 ms
都道府県の上位(10 年の合計) 横棒 10 行 / 387 ms
上位 5 県の年別 表 50 行 / 321 ms

どれも 0.3 秒前後。470 行しか読まないので当然です。

10 回ぶんの実行ログ

ダッシュボードのペイン

Dashboard Pro のテンプレート(KPI カード・カテゴリ別・ランキングなど)は、分類フィールドに選択肢の項目しか選べません。都道府県を文字列1行にしていると候補に出ないので、空のペインに kSQL を直接書きました。

-- 年別の売上(棒)
SELECT 年, SUM(売上) AS 売上 FROM LAPP_集計 GROUP BY 年 ORDER BY 年;

-- 都道府県の上位(横棒)
SELECT 都道府県, SUM(売上) AS 売上 FROM LAPP_集計 GROUP BY 都道府県 ORDER BY 売上 DESC LIMIT 10;

どちらも kSQL なので、アクション側と同じ書き方で済みます。都道府県をドロップダウンにしておけば、テンプレートからも作れます。

線引き(できないこと)

正直に書いておきます。

  • kSQL アクションは押した人のブラウザーで動きます。夜間バッチはできません。 誰かがボタンを押します。定期実行が要るなら kSQL Flow(CLI)や kSQL ジョブ実行プラグインの領分です
  • 1 年だけ見るなら、事前集計は要りません。 WHERE に書いた kintone の関数は REST にそのまま渡るので、絞り込みだけで足ります。事前集計が効くのは、年をまたいで横に並べたいときです
  • GROUP BY のある UPSERT は、元が 0 件のグループを書きません。 放っておくと消えた都道府県の行が前の値のまま残り、合計がずれます。上の「消えた都道府県を 0 にする」の形にしてください

まとめ

  • Dashboard Pro の上限はペインごとに 500〜50,000 件(既定 10,000)。10 年分 10 万件は上限を上げても届かない
  • 件数より先に効くのは API。複数の人が何回も開くので、1 日 5,700 回が 400 回になる差は大きい(10 人 × 10 回。直接のほうは試算、集計のほうは実測)
  • 上限に当てない設計にする。今回のデータなら年ごとに分けるだけで、読み取りの上限(既定 10,000)に収まる。1 年が 10,000 件を超えたら、上限を上げるのではなく分割の単位を細かくする(月単位にするなら、集計キーも「年月 × 都道府県」に変える)
  • 複合キーは連結した文字列 + 重複禁止、集計の軸は元のアプリに持たせる
  • 消えたグループは 0 で更新する。連続した軸(日・月・年)は GENERATE_SERIES × LEFT JOIN、飛び飛びのキーは 0 の行を UNION ALL

関連記事

参考リンク

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?