Google Big Query レガシーSQLの構文でハマったこと

こんにちは、kisseです。
今日は、Google Big QueryのレガシーSQLの構文についてのメモです。

現在は、標準SQLという方が推奨されているようですが、事情によりレガシーSQLを使う方は参考にしてください!

僕は、基本的にmysqlとBig Queryしか使ったことがないので、mysqlとの違いが焦点になります。




GROUP BY句において関数が使用できない

結構どハマりしました。

例えばmysqlだと、

SELECT
    some_func(column_a) AS column_a2,
    count(*)
FROM
    some_table
GROUP BY
    some_func(column_a)

このような書き方しますよね??
GROUP BY句にSELECT句で命名した名前を入れるとエラーが帰ってきます。

でもレガシーSQLだと上記のSQLではエラーが発生します。

レガシーSQLを使う場合には、以下のように記述してください。

SELECT
  some_func(column_a) AS columns_a2,
  count(*)
FROM
  some_table
GROUP BY
  column_a2

mysqlでは出来ない、SELECT句で命名した名前しかGROUP BY句では指定できず、関数を使うとエラー出ます。
これなかなか厄介で、サブクエリで1つだけカラムを指定した上でINで条件指定することが出来なくなったりします。
(もしかしたら他に方法があるかもしれないけど、単純には行かなさそうです。)

自然結合にはINNER JOINを使わなければいけない

mysqlでテーブルの自然結合するには、FROM句で2つのテーブルを指定してからWHERE句で結合カラムを指定します。
(もちろん、mysqlでもINNER JOINを用いた自然結合はできる。)
しかし、BigQueryではそのような形式での自然結合を行うことができません。(!?)
FROM句にテーブルを2つ記載すると、UNION ALLの意味になります(!?!?)

SELECT
    table1.*,
    table2.some_column,
    ...
FROM
    table1,
    table2
WHERE
    table1.table2_id = table2.id

上記はmysqlでは動作しますが、Big Queryではエラーが帰ってきます。

SELECT
    table1.*,
    table2.some_column,
    ...
FROM
    table1
    INNER JOIN
        table2
    ON
        table1.table2_id = table2.id

mysqlでもこのように書いた方が可読性は高い気がしますねー。




GROUP BYで特定の行を取り出すには

mysqlではGROUP BYでグループ化を行った後に特定のカラムに対してMAX()やMIN()を適用すると、その結果に対応したレコードが取得できます。
(公式のドキュメントを見ると、そのような記述が見つけられなくて不安になっているんですけど…。知っている方教えてください。)
Big Queryではそのような取得の方法はできません。
サブクエリで、MAX()なりMIN()なりの値を取り出したあとに、自己結合を行って条件指定するとそのようなレコードを取得することができました。

おわり

以上の3点でめちゃめちゃハマったので書きました。
これからBig Query初めて使うって方は標準SQLを使った方がいいと思います!
レガシーSQL使わなきゃいけないのでなければ、標準SQLの方が便利みたいです。

(実際僕も標準SQL使ってよかったらしいので、これからそっちにしようかと思ってるところです。)

最後まで読んでいただきありがとうございます!

あわせて読みたい