やっとクエリの準備ができました!
と、いうことで、どんな話をしようとしていたかというと、リソースに開始日と終了日を持つと、ある期間に有効だったデータを取得するのが難しくなるかどうか、という議論です。そんなデータの持ち方したら、複雑になってしまうのでダメだというご指摘を受けたことがあって、意外と簡単になりますよ~、という話です。
先ほどのデータ、ビジュアル的に表すと以下のようになります。2001年1月1日から2004年12月31日の期間に販売されていた書籍を取り出すとどうなるでしょうか。
このような有効期間のある問い合わせの場合、考えなければならないバターンを単純化すると、以下のように、6パターンになります。
ここで、StartからEndの範囲内で有効だったリソースは、②、④、⑤、⑥の4種類となります。まじめにやると、
②(Start ≦ 開始日 AND 終了日 ≦ End)
OR
④(開始日 ≦ Start AND End ≦ 終了日)
OR
⑤(開始日 ≦ Start AND Start ≦ 終了日)
OR
⑥(開始日 ≦ End AND End ≦ 終了日)
と、いうことになります。確かにこれは手間だし、複雑になるのが嫌だという抵抗も、もっともかもしれません。これをSQLで表現すると、以下のようになります。
SELECT BookNo, BookName
FROM BOOKS.BOOKS
WHERE ('2001-01-01' <= StartDate AND EndDate <= '2004-12-31')
OR (StartDate <= '2001-01-01' AND '2004-12-31' <= EndDate)
OR (StartDate <= '2001-01-01' AND '2001-01-01' <= EndDate)
OR (StartDate <= '2004-12-31' AND '2004-12-31' <= EndDate)
BigQueryで実行してみると予想通り、ちゃんと6件取得できました。
それでは、お待ちかねの改案です。実は、この問い合わせ、上記の①と③以外を検索する、と読み替えられます。
NOT( ①(終了日 < Start) OR ③(End < 開始日) )
意外とシンプルですね。SQLで表現すると以下の通りです。結果も変わりませんね。
SELECT BookNo, BookName
FROM BOOKS.BOOKS
WHERE NOT (EndDate < '2001-01-01' OR '2004-12-31' < StartDate)
ド・モルガンの法則で書き換えて整形すると以下のようになります。さらにシンプルになりました。結果も同じになりました。
SELECT BookNo, BookName
FROM BOOKS.BOOKS
WHERE '2001-01-01' <= EndDate AND StartDate <= '2004-12-31'
ある四角形の領域に重なる線分を探す、という問題を見つけましたが、今回のケースと同じ問題として考えられますので、興味のある方はチャレンジしてみてください。
BigQueryまずは使ってみましたが、実際の業務で使っていくためには、もう少し調査が必要ですね。
- CREATE TABLE文などのスクリプトでテーブル作成するやり方
- 利用可能なデータ型
- NO以外のカラム名として利用できない予約語
- オンプレミスのデータをBigQueryへ読み込むやり方
あと、上の画像のクエリ結果のところにある「データポータルで調べる」が気になります!ユーザーにも使えるようなものなのかどうか、後ほど調べてみます。
今回はここまでです。
“BigQueryまずは使ってみよう[3/3](SELECT編)” への1件の返信