Beam ZetaSQL クエリ構文
クエリステートメントは、1 つ以上のテーブル、ストリーム、または式をスキャンし、計算された結果行を返します。
SQL 構文
query_statement: query_expr query_expr: [ WITH with_query_name AS ( query_expr ) [, ...] ] { select | ( query_expr ) | query_expr set_op query_expr } [ [ ORDER BY expression [{ ASC | DESC }] [, ...] ] LIMIT count [ OFFSET skip_rows ] ] select: SELECT [ ALL | DISTINCT ] { * | expression [ [ AS ] alias ] } [, ...] [ FROM from_item ] [ WHERE bool_expression ] [ GROUP BY expression [, ...] ] [ HAVING bool_expression ] set_op: UNION { ALL | DISTINCT } | INTERSECT { ALL | DISTINCT } | EXCEPT { ALL | DISTINCT } from_item: { table_name [ [ AS ] alias ] | join | ( query_expr ) [ [ AS ] alias ] | with_query_name [ [ AS ] alias ] } table_name: identifier [ . identifier ...] join: from_item [ join_type ] JOIN from_item ON bool_expression join_type: { INNER | FULL [OUTER] | LEFT [OUTER] | RIGHT [OUTER] }
表記
- 角かっこ "[ ]" はオプションの句を示します。
- 丸かっこ "( )" はリテラルの丸かっこを示します。
- 縦棒 "|" は論理 OR を示します。
- 中かっこ "{ }" はオプションのセットを囲みます。
- 角かっこ内のカンマとそれに続く省略記号 "[, ... ]" は、先行する項目がカンマ区切りのリストで繰り返すことができることを示します。
SELECT リスト
構文
SELECT [ ALL ]
{ * | expression [ [ AS ] alias ] } [, ...]
SELECT リストは、クエリが返す列を定義します。SELECT リストの式は、対応する FROM 句の from_item 内の列を参照できます。
SELECT リストの各項目は次のいずれかです。
- *
式
SELECT *
SELECT * は、select star と呼ばれることが多く、クエリ全体を実行した後に可視になる列ごとに 1 つの出力列を生成します。
SELECT * FROM (SELECT "apple" AS fruit, "carrot" AS vegetable);
+-------+-----------+
| fruit | vegetable |
+-------+-----------+
| apple | carrot |
+-------+-----------+SELECT 式
注意: 最上位の SELECT では、明示的に選択した列名を使用するか、式を使用する場合は明示的なエイリアスを使用する必要があります。
SELECT リストの項目は式にすることができます。これらの式は単一の値に評価され、オプションの明示的な alias を持つ 1 つの出力列を生成します。
式に明示的なエイリアスがない場合は、可能な場合は暗黙的なエイリアスのルールに従って暗黙的なエイリアスを受け取ります。それ以外の場合、列は匿名になり、クエリの他の場所で名前で参照することはできません。
SELECT 修飾子
次のように、SELECT クエリから返される結果を変更できます。
SELECT ALL
SELECT ALL ステートメントは、重複する行を含むすべての行を返します。SELECT ALL は SELECT のデフォルトの動作です。
エイリアス
SELECT リストのエイリアスの構文と可視性の詳細については、エイリアスを参照してください。
FROM 句
FROM 句は、行を取得するテーブルまたはストリームを示し、それらの行を結合して、クエリの残りの部分で処理するための一連の行を生成する方法を指定します。
構文
from_item: { table_name [ [ AS ] alias ] | join | ( query_expr ) [ [ AS ] alias ] | with_query_name [ [ AS ] alias ] }
table_name
Beam SQL でクエリ可能なデータソースの完全修飾 SQL 名。ドットで区切られた識別子のリストを使用して、標準 SQL の字句構造で指定されます。文字、数字、またはアンダースコア以外の文字を含む識別子を囲むには、バッククォートを使用する必要があります。
SELECT * FROM bigquery.table.`my-project`.baseball.roster; SELECT * FROM pubsub.topic.`my-project`.incoming_events;
join
以下のJOIN タイプを参照してください。
select
( select ) [ [ AS ] alias ] はテーブルサブクエリです。
with_query_name
WITH 句 (「WITH 句」を参照) のクエリ名は、FROM 句の任意の場所で参照できる一時テーブルの名前のように機能します。以下の例では、subQ1 と subQ2 は with_query_names です。
例
WITH subQ1 AS (SELECT * FROM Roster WHERE SchoolID = 52), subQ2 AS (SELECT SchoolID FROM subQ1) SELECT DISTINCT * FROM subQ2;
クエリの期間中、テーブル名を修飾しない限り、WITH 句は同じ名前の永続的なテーブルを非表示にします。例:
db.Roster.
サブクエリ
サブクエリは、別のステートメントの内側に表示されるクエリで、かっこで囲まれて記述されます。これらは「サブ SELECT」または「ネストされた SELECT」とも呼ばれます。完全な SELECT 構文はサブクエリで有効です。
サブクエリには 2 つのタイプがあります。
- 式サブクエリ。式が有効なクエリで使用できます。式サブクエリは単一の値を返します。
- テーブルサブクエリ。
FROM句でのみ使用できます。外部クエリは、サブクエリの結果をテーブルとして扱います。
両方のタイプのサブクエリの周りに括弧が必要であることに注意してください。
例
SELECT AVG ( PointsScored )
FROM
( SELECT PointsScored
FROM Stats
WHERE SchoolID = 77 )オプションで、テーブルサブクエリにはエイリアスを設定できます。
例
SELECT r.LastName
FROM
( SELECT * FROM Roster) AS r;エイリアス
FROM 句のエイリアスの構文と可視性の詳細については、エイリアスを参照してください。
JOIN タイプ
構文
join: from_item [ join_type ] JOIN from_item ON bool_expression join_type: { INNER | FULL [OUTER] | LEFT [OUTER] | RIGHT [OUTER] }
JOIN 句は 2 つの from_item をマージし、SELECT 句が 1 つのソースとしてクエリできるようにします。join_type と ON 句 (「結合条件」) は、2 つの from_item から行を結合および破棄して 1 つのソースを形成する方法を指定します。
すべての JOIN 句には join_type が必要です。
[INNER] JOIN
INNER JOIN または単に JOIN は、2 つの from_item のデカルト積を効果的に計算し、結合条件を満たさないすべての行を破棄します。「効果的に」とは、実際にはデカルト積を計算せずに INNER JOIN を実装できる可能性があることを意味します。
FULL [OUTER] JOIN
FULL OUTER JOIN (または単に FULL JOIN) は、結合条件を満たす両方の from_item 内のすべての行のすべてのフィールドを返します。
FULL は、結合条件を満たさない場合でも、両方の from_item からすべての行が返されることを示します。
OUTER は、一方の from_item からの特定の行がもう一方の from_item 内のどの行にも結合しない場合、その行はもう一方の from_item からのすべての列に対して NULL で返されることを示します。
LEFT [OUTER] JOIN
2 つの from_item の LEFT OUTER JOIN (または単に LEFT JOIN) の結果は、結合述語を満たす右の from_item に行がない場合でも、JOIN 句内の左の from_item のすべての行を常に保持します。
LEFT は、左の from_item からすべての行が返されることを示します。左の from_item からの特定の行が右の from_item 内のどの行にも結合しない場合、その行は右の from_item からのすべての列に対して NULL で返されます。左の from_item 内のどの行にも結合しない右の from_item からの行は破棄されます。
RIGHT [OUTER] JOIN
RIGHT OUTER JOIN (または単に RIGHT JOIN) の結果は、LEFT OUTER JOIN の結果と似ており、対称です。
ON 句
ON 句には bool_expression が含まれます。結合された行 (2 つの行を結合した結果) は、bool_expression が TRUE を返した場合に結合条件を満たします。
例
SELECT * FROM Roster INNER JOIN PlayerStats
ON Roster.LastName = PlayerStats.LastName;JOIN のシーケンス
FROM 句には、複数の JOIN 句を順番に含めることができます。
例
SELECT * FROM a LEFT JOIN b ON TRUE LEFT JOIN c ON TRUE;ここで、a、b、および c は任意の from_item です。JOIN は左から右にバインドされますが、括弧を挿入して別の順序でグループ化できます。
WHERE 句
構文
WHERE bool_expressionWHERE 句は、各行を bool_expression に対して評価することによって行をフィルタリングし、TRUE を返さない (つまり、FALSE または NULL を返す行) すべての行を破棄します。
例
SELECT * FROM Roster
WHERE SchoolID = 52;bool_expression には複数のサブ条件を含めることができます。
例
SELECT * FROM Roster
WHERE STARTS_WITH(LastName, "Mc") OR STARTS_WITH(LastName, "Mac");WHERE 句では、SELECT リストから列エイリアスを参照することはできません。
GROUP BY 句
構文
GROUP BY expression [, ...]
GROUP BY句は、テーブル内の行をGROUP BY句のexpressionに対して非一意の値を持つ行をグループ化します。ソーステーブル内の複数の行がexpressionに対して非一意の値を持つ場合、GROUP BY句は単一の結合された行を生成します。GROUP BYは、集計関数がSELECTリストに存在する場合、または出力の冗長性を排除するためによく使用されます。expressionのデータ型は、グループ化可能である必要があります。
例
SELECT SUM(PointsScored), LastName
FROM PlayerStats
GROUP BY LastName;GROUP BY句は、SELECTリスト内の式の名前を参照できます。また、GROUP BY句では、整数値を使用してSELECTリスト内の式への序数参照も許可されています。1はSELECTリストの最初の式を、2は2番目の式を、というように参照します。式リストは、序数と式の名前を組み合わせることができます。
例
SELECT SUM(PointsScored), LastName, FirstName
FROM PlayerStats
GROUP BY LastName, FirstName;上記のクエリは以下と同等です。
SELECT SUM(PointsScored), LastName, FirstName
FROM PlayerStats
GROUP BY 2, FirstName;GROUP BY句はエイリアスを参照することもできます。クエリにSELECT句にエイリアスが含まれている場合、これらのエイリアスは対応するFROM句の名前を上書きします。
例
SELECT SUM(PointsScored), LastName as last_name
FROM PlayerStats
GROUP BY last_name;HAVING 句
構文
HAVING bool_expressionHAVING句はWHERE句に似ています。これは、bool_expressionに対して評価されたときにTRUEを返さない行をフィルタリングします。
WHERE句と同様に、bool_expressionはブール値を返す任意の式にすることができ、複数のサブ条件を含むことができます。
HAVING句は、次の点でWHERE句と異なります。
HAVING句を使用するには、クエリにGROUP BYまたは集計が存在する必要があります。HAVING句は、GROUP BYと集計の後、ORDER BYの前に発生します。これは、HAVING句が結果セット内の集計された行ごとに1回評価されることを意味します。これは、GROUP BYと集計の前に評価されるWHERE句とは異なります。
HAVING句は、FROM句を介して利用可能な列と、SELECTリストのエイリアスを参照できます。HAVING句で参照される式は、GROUP BY句に表示されるか、集計関数の結果である必要があります。
SELECT LastName
FROM Roster
GROUP BY LastName
HAVING SUM(PointsScored) > 15;クエリにSELECT句にエイリアスが含まれている場合、これらのエイリアスはFROM句の名前を上書きします。
SELECT LastName, SUM(PointsScored) AS ps
FROM Roster
GROUP BY LastName
HAVING ps > 0;必須の集計
集計はHAVING句自体に存在する必要はありませんが、集計は次のいずれかの形式で少なくとも1つ存在する必要があります。
SELECTリストの集計関数。
SELECT LastName, SUM(PointsScored) AS total
FROM PlayerStats
GROUP BY LastName
HAVING total > 15;「HAVING」句の集計関数。
SELECT LastName
FROM PlayerStats
GROUP BY LastName
HAVING SUM(PointsScored) > 15;SELECTリストとHAVING句の両方の集計。
集計関数がSELECTリストとHAVING句の両方に存在する場合、集計関数とそれらが参照する列は同じである必要はありません。以下の例では、2つの集計関数COUNT()とSUM()が異なり、異なる列も使用しています。
SELECT LastName, COUNT(*)
FROM PlayerStats
GROUP BY LastName
HAVING SUM(PointsScored) > 15;LIMIT 句と OFFSET 句
構文
[ ORDER BY expression [{ASC | DESC}] [,...] ] LIMIT count [ OFFSET skip_rows ]ORDER BY句は、結果セットのソート基準として列または式を指定します。ORDER BY句が存在しない場合、クエリの結果の順序は定義されません。デフォルトのソート方向はASCで、expressionの値の昇順で結果をソートします。DESCは結果を降順にソートします。FROM句またはSELECTリストの列エイリアスを使用できます。クエリにSELECT句にエイリアスが含まれている場合、これらのエイリアスは対応するFROM句の名前を上書きします。
複数の列で順序付けすることが可能です。
値を順序付けする場合、次のルールが適用されます。
- NULL:
ORDER BY句のコンテキストでは、NULLは可能な最小値です。つまり、NULLはASCソートでは最初に、DESCソートでは最後に表示されます。
LIMITは、INT64型の負でないcountを指定し、count行以下の行が返されます。LIMIT 0は0行を返します。セット演算がある場合、LIMITはセット演算が評価された後に適用されます。
OFFSETは、INT64型の負でないskip_rowsを指定し、テーブル内のそのオフセットからの行のみが考慮されます。
これらの句は、リテラル値またはパラメーター値のみを受け入れます。
LIMITおよびOFFSETによって返される行は、これらの演算子がORDER BYの後に使用されない限り、指定されません。
WITH 句
WITH句は、1つ以上の名前付きサブクエリの結果を一時テーブル名にバインドします。導入された各テーブル名は、同じクエリ式内の後続のSELECT式で表示されます。これには、次の種類のSELECT式が含まれます。
- 後続の
WITHバインディング内の任意のSELECT式 UNIONなどのセット演算子の両側のクエリ式内のトップレベルのSELECT式- 同じクエリ式内のサブクエリ内の
SELECT式
例
WITH subQ1 AS (SELECT SchoolID FROM Roster),
subQ2 AS (SELECT OpponentID FROM PlayerStats)
SELECT * FROM subQ1
UNION ALL
SELECT * FROM subQ2;WITH句のスコープ規則は次のとおりです。
- エイリアスは、
WITH句で導入されたエイリアスが、同じWITH句内の後のサブクエリと、WITH句の下のクエリでのみ表示されるようにスコープ設定されます。 - 同じ
WITH句で導入されたエイリアスは一意である必要がありますが、同じエイリアスを同じクエリ内の複数のWITH句で使用できます。ローカルエイリアスは、ローカルエイリアスが表示される場所で、外部エイリアスを上書きします。
Beam SQLはWITH RECURSIVEをサポートしていません。
エイリアス
エイリアスは、クエリに存在するテーブル、列、または式に付けられた一時的な名前です。SELECTリストまたはFROM句で明示的なエイリアスを導入できます。
明示的なエイリアス構文
FROM句またはSELECTリストのいずれかで明示的なエイリアスを導入できます。
FROM句では、[AS] aliasを使用して、テーブル、配列、サブクエリなど、任意の項目の明示的なエイリアスを導入できます。ASキーワードはオプションです。
例
SELECT s.FirstName, s2.SongName
FROM Singers AS s, (SELECT * FROM Songs) AS s2;[AS] aliasを使用して、SELECTリストの任意の式の明示的なエイリアスを導入できます。ASキーワードはオプションです。
例
SELECT s.FirstName AS name, LOWER(s.FirstName) AS lname
FROM Singers s;明示的なエイリアスの可視性
クエリで明示的なエイリアスを導入した後、クエリの他の場所でそのエイリアスを参照できる場所に制限があります。エイリアスの表示に関するこれらの制限は、Beam SQLの名前スコープ規則の結果です。
FROM句のエイリアス
Beam SQLは、FROM句のエイリアスを左から右に処理し、エイリアスはFROM句の後続のパス式にのみ表示されます。
例
SingersテーブルにARRAY型のConcerts列があると仮定します。
SELECT FirstName
FROM Singers AS s, s.Concerts;無効
SELECT FirstName
FROM s.Concerts, Singers AS s; // INVALID.FROM句のエイリアスは、同じFROM句のサブクエリには表示されません。FROM句のサブクエリは、同じFROM句内の他のテーブルへの関連参照を含めることはできません。
無効
SELECT FirstName
FROM Singers AS s, (SELECT (2020 - ReleaseDate) FROM s) // INVALID.FROMのテーブルの任意の列名を、テーブル名での修飾の有無にかかわらず、クエリ内のエイリアスとしてどこでも使用できます。
例
SELECT FirstName, s.ReleaseDate
FROM Singers s WHERE ReleaseDate = 1975;SELECTリストのエイリアス
SELECTリストのエイリアスは、次の句にのみ表示されます。
GROUP BY句ORDER BY句HAVING句
例
SELECT LastName AS last, SingerID
FROM Singers
ORDER BY last;GROUP BY、ORDER BY、HAVING 句での明示的なエイリアス
これら3つの句、GROUP BY、ORDER BY、およびHAVINGは、次の値のみを参照できます。
FROM句内のテーブルとその任意の列。SELECTリストのエイリアス。
GROUP BYおよびORDER BYは、3番目のグループを参照することもできます。
SELECTリスト内の項目を参照する整数リテラル。整数1はSELECTリストの最初の項目を、2は2番目の項目を、というように参照します。
例
SELECT SingerID AS sid, COUNT(Songid) AS s2id
FROM Songs
GROUP BY 1
ORDER BY 2 DESC LIMIT 10;上記のクエリは以下と同等です。
SELECT SingerID AS sid, COUNT(Songid) AS s2id
FROM Songs
GROUP BY sid
ORDER BY s2id DESC LIMIT 10;あいまいなエイリアス
名前が曖昧な場合、つまり複数の固有のオブジェクトに解決できる場合、Beam SQLはエラーを提供します。
例
このクエリには、SingersとSongsの両方にSingerIDという名前の列があるため、テーブル間で競合する列名が含まれています。
SELECT SingerID
FROM Singers, Songs;このクエリには、SELECTリストで重複しているため、GROUP BY句で曖昧なエイリアスが含まれています。
SELECT FirstName AS name, LastName AS name,
FROM Singers
GROUP BY name;GROUP BY内のFROM句の列名とSELECTリストのエイリアス間の曖昧さ
SELECT UPPER(LastName) AS LastName
FROM Singers
GROUP BY LastName;上記のクエリは曖昧であり、GROUP BY句のLastNameがSingersの元の列LastNameを参照するか、値がUPPER(LastName)であるエイリアスAS LastNameを参照する可能性があるため、エラーが発生します。
パス式にも同じ曖昧さのルールが適用されます。tableに列xとyがあり、列zがSTRUCT型で、フィールドv、w、およびxがある次のクエリを考えてみましょう。
例
SELECT x, z AS T
FROM table T
GROUP BY T.x;エイリアスTは曖昧であり、GROUP BY句のT.xがtable.xまたはtable.z.xのいずれかを参照する可能性があるため、エラーが発生します。
名前が、基になる同じオブジェクトに解決される限り、列名とSELECTリストのエイリアスの両方である場合、GROUP BY、ORDER BY、またはHAVINGで曖昧ではありません。
例
SELECT LastName, BirthYear AS BirthYear
FROM Singers
GROUP BY BirthYear;エイリアスBirthYearは、基になる同じ列Singers.BirthYearに解決されるため、曖昧ではありません。
付録 A: サンプルデータを使った例
サンプルテーブル
次の3つのテーブルには、アスリート、その学校、およびシーズン中に獲得したポイントに関するサンプルデータが含まれています。これらのテーブルは、さまざまなクエリ句の動作を説明するために使用されます。
テーブルRoster
| LastName | SchoolID |
|---|---|
| Adams | 50 |
| Buchanan | 52 |
| Coolidge | 52 |
| Davis | 51 |
| Eisenhower | 77 |
Rosterテーブルには、選手名(LastName)と学校に割り当てられた一意のID(SchoolID)のリストが含まれています。
テーブルPlayerStats
| LastName | OpponentID | PointsScored |
|---|---|---|
| Adams | 51 | 3 |
| Buchanan | 77 | 0 |
| Coolidge | 77 | 1 |
| Adams | 52 | 4 |
| Buchanan | 50 | 13 |
PlayerStatsテーブルには、選手名(LastName)、特定のゲームで対戦した対戦相手に割り当てられた一意のID(OpponentID)、およびそのゲームでアスリートが獲得したポイント数(PointsScored)のリストが含まれています。
テーブルTeamMascot
| SchoolId | マスコット |
|---|---|
| 50 | ジャガーズ |
| 51 | ナイツ |
| 52 | レイカーズ |
| 53 | マスタングス |
TeamMascotテーブルには、ユニークな学校ID(SchoolID)と、その学校のマスコット(Mascot)のリストが含まれています。
JOIN タイプ
1) [INNER] JOIN
例
SELECT * FROM Roster JOIN TeamMascot
ON Roster.SchoolID = TeamMascot.SchoolID;結果
| LastName | Roster.SchoolId | TeamMascot.SchoolId | マスコット |
|---|---|---|---|
| Adams | 50 | 50 | ジャガーズ |
| Buchanan | 52 | 52 | レイカーズ |
| Coolidge | 52 | 52 | レイカーズ |
| Davis | 51 | 51 | ナイツ |
2) FULL [OUTER] JOIN
例
SELECT * FROM Roster FULL JOIN TeamMascot
ON Roster.SchoolID = TeamMascot.SchoolID;| LastName | Roster.SchoolId | TeamMascot.SchoolId | マスコット |
|---|---|---|---|
| Adams | 50 | 50 | ジャガーズ |
| Buchanan | 52 | 52 | レイカーズ |
| Coolidge | 52 | 52 | レイカーズ |
| Davis | 51 | 51 | ナイツ |
| Eisenhower | 77 | NULL | NULL |
| NULL | NULL | 53 | マスタングス |
3) LEFT [OUTER] JOIN
例
SELECT * FROM Roster LEFT JOIN TeamMascot
ON Roster.SchoolID = TeamMascot.SchoolID;結果
| LastName | Roster.SchoolId | TeamMascot.SchoolId | マスコット |
|---|---|---|---|
| Adams | 50 | 50 | ジャガーズ |
| Buchanan | 52 | 52 | レイカーズ |
| Coolidge | 52 | 52 | レイカーズ |
| Davis | 51 | 51 | ナイツ |
| Eisenhower | 77 | NULL | NULL |
4) RIGHT [OUTER] JOIN
例
SELECT * FROM Roster RIGHT JOIN TeamMascot
ON Roster.SchoolID = TeamMascot.SchoolID;結果
| LastName | Roster.SchoolId | TeamMascot.SchoolId | マスコット |
|---|---|---|---|
| Adams | 50 | 50 | ジャガーズ |
| Davis | 51 | 51 | ナイツ |
| Coolidge | 52 | 52 | レイカーズ |
| Buchanan | 52 | 52 | レイカーズ |
| NULL | NULL | 53 | マスタングス |
GROUP BY 句
例
SELECT LastName, SUM(PointsScored)
FROM PlayerStats
GROUP BY LastName;| LastName | SUM |
|---|---|
| Adams | 7 |
| Buchanan | 13 |
| Coolidge | 1 |
セット演算子
UNION
UNION演算子は、2つ以上のSELECTステートメントの結果セットを、各SELECTステートメントの結果セットから列をペアリングし、それらを垂直方向に連結することによって結合します。
例
SELECT Mascot AS X, SchoolID AS Y
FROM TeamMascot
UNION ALL
SELECT LastName, PointsScored
FROM PlayerStats;結果
| X | Y |
|---|---|
| ジャガーズ | 50 |
| ナイツ | 51 |
| レイカーズ | 52 |
| マスタングス | 53 |
| Adams | 3 |
| Buchanan | 0 |
| Coolidge | 1 |
| Adams | 4 |
| Buchanan | 13 |
INTERSECT
このクエリは、RosterとPlayerStatsの両方に存在するラストネームを返します。
SELECT LastName
FROM Roster
INTERSECT ALL
SELECT LastName
FROM PlayerStats;結果
| LastName |
|---|
| Adams |
| Coolidge |
| Buchanan |
EXCEPT
以下のクエリは、Rosterに存在し、PlayerStatsに存在しないラストネームを返します。
SELECT LastName
FROM Roster
EXCEPT DISTINCT
SELECT LastName
FROM PlayerStats;結果
| LastName |
|---|
| Eisenhower |
| Davis |
SELECTステートメントの順序を逆にすると、PlayerStatsに存在し、Rosterに存在しないラストネームが返されます。
SELECT LastName
FROM PlayerStats
EXCEPT DISTINCT
SELECT LastName
FROM Roster;結果
(empty)

