導入記事にある通りエクセルの神髄さんのSQL基礎問題にチャレンジしていきます。
お題
【SQL問題】
— エクセルの神髄 (@yamaoka_ss) 2025年10月28日
列「ID」は「○○-nnn-mmm」の形式です。
nnn,mmmは桁数不定です。
この時、「○○-nnn」ごとに件数を取得するSQLを作成してください。
※テーブル名は任意
※出力の並び順は問わない。 pic.twitter.com/Qgg1WRy5NH
言語化
ピボットテーブルと同じような表現をSQLで実現することになります。
- IDの内、2つ目の「-」の手前までを抽出
- 抽出したIDでグループ化
SQL化
IDからお題である「〇〇ーnnn」のデータを抽出します。
まずは2つ目の「‐」が何文字目にあるのかを確認します。
INSTRREV関数を利用して位置を確認します。
2つ目の「-」は省きたいので、INSTRREV関数で返ってきた値から1を引いています。
select instrrev(ID, '-') - 1 as 何文字目 from [Q3$A1:B11]

取得した何文字目かのデータを利用して、IDからグループ化したい箇所を抽出します。
抽出にはLEFT関数.mdを利用します。
Excel関数のLEFTと使い方は同じです。
select left (ID, instrrev(ID, '-') - 1) as ID抽出 from [Q3$A1:B11]

最後に抽出したIDを利用してデータをグループ化します。
データのグループ化はGROUP BY句を利用します。
select left (ID, instrrev(ID, '-') - 1) as ID , count(*) as 件数 from [Q3$A1:B11] group by left (ID, instrrev(ID, '-') - 1)

WITH句の代わり
上記の最終解答のSQLですが、「left (ID, instrrev(ID, '-') - 1)」という表記が2回出てきていて、少し野暮ったい感じがしますね。
こういう時にSQLではWITH句という構文を利用して記述を省略することが出来ます。
構文としてはWITH句でSQL文を記載して名前を付けておくと、SQL本文で設定した名前でSQLを作成することが出来ます。
VBAでいう変数のように使うことが出来ます。
WITH CTE名 AS ( SELECT ... ) SELECT * FROM CTE名 WHERE ...;
便利な機能ですが、残念ながらExcel × ADOではWITH句を利用することが出来ません。
その代わりと言ってはなんですが、ExcelのLET関数を使用することで同じように記載することが出来ます。
=LET(ID," left (ID, instrrev(ID, '-') - 1)", kfSQLSearch(" select " & ID & " as ID , count(*) as 件数 from [Q3$A1:B11] group by " & ID & "" ))
LET関数で「ID」を「left (ID, instrrev(ID, '-') - 1)」と定義しておくことで、SQL本文では「ID」と記載するだけで上述のSQLと同じ内容を表現することが出来ます。
このようにLET関数を利用することで、SQL本文がスッキリしますし「ID」の箇所を編集する際もWITH句の箇所を変更するだけで対応できるようになります。
まとめ
SQLを使うことでオートフィルタのような機能だけでなく、ピボットテーブルのようなデータ抽出も簡単に実現することが出来ます。