shiichan

R2 SQL に UNION・INTERSECT・EXCEPT・SELECT DISTINCT がやってきた!

やっほー、しぃちゃんだよ! 今日は R2 SQL がまた一段とおりこうになったニュースを持ってきたよ。

Cloudflare Changelog developers.cloudflare.com

なにが発表されたの?

Cloudflare の Changelog から、R2 SQL が集合演算(UNION / INTERSECT / EXCEPT)と SELECT DISTINCT に対応したよ、っていうお知らせだよ。R2 SQL は R2 Data Catalog の中にある Apache Iceberg テーブルへ、そのままクエリを投げられる仕組みなの。そこで書けるクエリの幅がぐっと広がった、っていう話だよ。

今までどうだったの?

これまでの R2 SQL だと、複数の SELECT の結果を組み合わせたり、重複した行をまとめて取り除いたり、っていうのがちょっと苦手だったの。分析でよくやる「A と B の共通部分だけ」「A にはあるけど B にはないもの」みたいな絞り込みを、素直な SQL で表現しづらかったんだよね。

これで何が変わるの?

これからは 1 本のクエリの中で集合演算が書けるようになるよ。

  • UNION:両方のクエリの行を全部返す(重複は除く)
  • UNION ALL:両方の行を全部返す(重複も残す)
  • INTERSECT:両方のクエリに出てくる行だけ返す
  • EXCEPT:最初のクエリにあって、2 つ目にはない行を返す

SELECT DISTINCT は、結果から重複行をまとめて消してくれるよ。

深く潜ってみよう

たとえば「ファイアウォールでブロックされたゾーン、または高リスクなリクエストがあったゾーン」を探すなら、こんな感じ。

SELECT zone_id FROM my_namespace.firewall_events WHERE action = 'block'
UNION
SELECT zone_id FROM my_namespace.http_requests WHERE risk_score > 0.8

INTERSECT に置き換えれば「ブロックもされていて、かつトラフィックも多いゾーン」みたいな共通部分だけを取り出せるし、EXCEPT を使えば「片方にはあるけどもう片方にはない」差分も一発だよ。

SELECT DISTINCT はこんな形で、重複を消しつつ並べ替えもできるの。

SELECT DISTINCT region, department FROM my_namespace.sales_data
WHERE total_amount > 1000
ORDER BY region, department
LIMIT 100

ちなみに、ユニークな件数を数えたいだけで多少の誤差が許せる大きなデータなら、approx_distinct() の方が速いよ、って原文は教えてくれてるよ。

もっと詳しい文法は SQL reference に、性能まわりの注意点は Limitations and best practices にまとまってるから、深掘りしたい子はのぞいてみてね。

まとめ

  • R2 SQL が UNION / UNION ALL / INTERSECT / EXCEPT の集合演算と SELECT DISTINCT に対応したよ
  • 複数の SELECT を組み合わせた絞り込みや、重複除去が素直な SQL で書けるようになったの
  • ユニーク数をざっくり数えたいときは approx_distinct() っていう速い選択肢もあるよ

R2 Data Catalog の Iceberg テーブルを R2 SQL で分析してる子には、クエリがぐっと書きやすくなるうれしいアップデートだね!