SQLの処理順序を意識していますか?
皆さんはSQLを書くときに、処理の順序を意識していますか?SQLクエリは複数の句から構成され、それぞれがデータの取得や操作に影響を与えます。SQLは次のような順序で処理が行われます。
1.FROM句
2.JOIN句
3.WHERE句
4.GROUP BY句
5.HAVING句
6.SELECT句
7.ORDER BY句
8.LIMIT句
今回はSQLを書く方はみんな知っていてほしいSQLの処理順序について、作業をしていると出てきがちな3つの疑問を挙げながら解説していきます。BigQueryのGA4データで解説しますが、考え方はどのSQL、データソースでも同じです。
これまでなんとなくSQLを書いていた方、SQLの処理順序についてあまり意識していなかった方はご参考になれば幸いです。
こちらのコラムはSQLの基本的な説明や解説ではなく、すでにSQLを書いている方向けの内容となっています。
疑問1「LIMITで制限しているのに処理の大きさが変わらないのはなぜ?」
画像の下のクエリではLIMIT句で1行に絞っているのに、上の使っていないクエリと同じ処理の大きさです。
「試しに数行だけクエリ結果がみたかったからLIMITで絞ったのに、思ったよりも時間がかかるのはなぜだろう?」と思った方もいるのではないでしょうか。
これは、LIMIT句の実行処理順番が最後なのが原因です。
FROM句でテーブルを指定し、SELECT句の「*」で全てのカラムを指定し、最後にLIMIT句で行数を1行にしています。SELECT句で持ってきた時点でデータの大きさが決まっているので、最後にLIMIT句で1行に絞っても処理の量は変わりません。
データを制限して処理の量を小さくしたいようであれば、WHEREで絞るなど抽出データ自体を小さくする必要があります。
疑問2「SELECTの中にまたSELECT、これってどうなっているの?」
画像のように、SQLの中に入れ子でSQLを書くことをサブクエリ(副問合せ)と呼びます。
SELECT句だけでなくFROM句やWHERE句などで使え、SELECT文をまとめられるので便利な記述方法です。
GA4はページビューやスクロールを全てイベント単位で計測しますが、BigQueryも同様にイベント単位でデータが蓄積していきます。さまざまなイベントから特定のイベントを抽出するときにサブクエリが活躍します。
GA4データで「page_location」イベントをサブクエリで抽出する例
例えば↑のクエリでは「event_params」から「page_location」に該当する値をサブクエリで持ってきています。
サブクエリの結果に対して外側のクエリの結果を返すので、カッコ内のサブクエリは先に、外側のクエリは後から処理されます。
英語のリファレンスページになりますが、BigQueryではさまざまなサブクエリがサポートされていますので詳しくはこちらをご参照ください。
疑問3「SELECTで別名を定義したのに、WHEREで使えないのはなぜ?」
画像のクエリではSELECT句のASで定義した列名「page_location」をWHERE句内で「basic」が含むページだけに絞ろうとしていますが、エラーになっています。これはSQLがWHERE→SELECTという順番で処理されるので、WHEREを読み込んだ時点では「page_location」ってなんだ?となっているからです。
SELECTで定義した別名で絞り込みを行う場合はサブクエリで抽出しておく、もしくはWITH句で集計してからWHEREで絞るなど、工夫が必要です。
↑WITHで一度集計してからWHERE内で「page_location」から「basic」をしぼったサンプル
ちなみに、ORDER BY句は処理順序がSELECT句より後なのでSELECT句内のASで定義した列名が使えます。また、GROUP BY句は順序的にはSELECT句の方が後に処理されますが、BigQueryの拡張機能によってSELECT句内のASで定義した列名を使うことができます。ただし、標準SQLではGROUP BY句では別名は使えないなど、SQLによってまちまちです。
おわりに
SQLの処理順序を理解することで、効率的なクエリの作成やパフォーマンスの最適化に役立ちます。
目的によってクエリの書き方を変えた方がいい場合があるので、SQLが処理される順序を意識しながら、効果的にクエリを回していきましょう。