SELECT

構文

[ WITH with_query [, ...] ]
SELECT [ ALL | DISTINCT ] select_expr [, ...]
[ FROM from_item [, ...] ]
[ WHERE condition ]
[ GROUP BY [ ALL | DISTINCT ] grouping_element [, ...] ]
[ HAVING condition]
[ { UNION | INTERSECT | EXCEPT } [ ALL | DISTINCT ] select ]
[ ORDER BY expression [ ASC | DESC ] [, ...] ]
[ OFFSET count [ { ROW | ROWS } ] ]
[ { LIMIT [ count | ALL ] } ]

ここで、from_item は以下のいずれかです。

table_name [ [ AS ] alias [ ( column_alias [, ...] ) ] ]
from_item join_type from_item [ ON join_condition | USING ( join_column [, ...] ) ]

そして、join_type は以下のいずれかです。

[ INNER ] JOIN
LEFT [ OUTER ] JOIN
RIGHT [ OUTER ] JOIN
FULL [ OUTER ] JOIN
CROSS JOIN

そして、grouping_element は以下のいずれかです。

()
expression
GROUPING SETS ( ( column [, ...] ) [, ...] )
CUBE ( column [, ...] )
ROLLUP ( column [, ...] )

説明

ゼロ個以上のテーブルから行を取得します。

WITH 句

WITH 句は、クエリ内で使用するための名前付き関係を定義します。ネストされたクエリをフラット化したり、サブクエリを簡略化したりすることができます。たとえば、以下のクエリは同等です。

SELECT a, b
FROM (
  SELECT a, MAX(b) AS b FROM t GROUP BY a
) AS x;

WITH x AS (SELECT a, MAX(b) AS b FROM t GROUP BY a)
SELECT a, b FROM x;

これは複数のサブクエリでも機能します。

WITH
  t1 AS (SELECT a, MAX(b) AS b FROM x GROUP BY a),
  t2 AS (SELECT a, AVG(d) AS d FROM y GROUP BY a)
SELECT t1.*, t2.*
FROM t1
JOIN t2 ON t1.a = t2.a;

さらに、WITH 句内の関係はチェーンすることができます。

WITH
  x AS (SELECT a FROM t),
  y AS (SELECT a AS b FROM x),
  z AS (SELECT b AS c FROM y)
SELECT c FROM z;

警告

現在、WITH 句の SQL は、名前付き関係が使用される場所であればどこでもインライン化されます。つまり、関係が複数回使用され、クエリが非決定論的である場合、結果が毎回異なる可能性があります。

GROUP BY 句

GROUP BY 句は、SELECT ステートメントの出力を、一致する値を含む行のグループに分割します。単純な GROUP BY 句には、入力列で構成される任意の式を含めることができます。または、出力列を位置(1 から始まる)で選択する序数にすることもできます。

以下のクエリは同等です。どちらも nationkey 入力列で出力をグループ化しており、最初のクエリは出力列の序数位置を使用し、2 番目のクエリは入力列名を使用しています。

SELECT count(*), nationkey FROM customer GROUP BY 2;

SELECT count(*), nationkey FROM customer GROUP BY nationkey;

GROUP BY 句は、select ステートメントの出力に表示されない入力列名で出力をグループ化できます。たとえば、次のクエリは、入力列 mktsegment を使用して customer テーブルの行数を生成します。

SELECT count(*) FROM customer GROUP BY mktsegment;
 _col0
-------
 29968
 30142
 30189
 29949
 29752
(5 rows)

SELECT ステートメントで GROUP BY 句が使用される場合、すべての出力式は集計関数または GROUP BY 句に存在する列である必要があります。

複雑なグループ化操作

Presto は、GROUPING SETSCUBEROLLUP 構文を使用した複雑な集計もサポートしています。この構文により、ユーザーは単一のクエリで複数の列セットの集計を必要とする分析を実行できます。複雑なグループ化操作では、入力列で構成される式のグループ化はサポートされていません。列名または序数のみが許可されます。

複雑なグループ化操作は、多くの場合、以下の例に示すように、単純な GROUP BY 式の UNION ALL と同等です。ただし、集計のデータソースが非決定論的である場合、この等価性は適用されません.

GROUPING SETS

グループ化セットにより、ユーザーはグループ化する列の複数のリストを指定できます。グループ化列の特定のサブリストに含まれていない列は、NULL に設定されます。

SELECT * FROM shipping;
 origin_state | origin_zip | destination_state | destination_zip | package_weight
--------------+------------+-------------------+-----------------+----------------
 California   |      94131 | New Jersey        |            8648 |             13
 California   |      94131 | New Jersey        |            8540 |             42
 New Jersey   |       7081 | Connecticut       |            6708 |            225
 California   |      90210 | Connecticut       |            6927 |           1337
 California   |      94131 | Colorado          |           80302 |              5
 New York     |      10002 | New Jersey        |            8540 |              3
(6 rows)

GROUPING SETS のセマンティクスは、このクエリの例で示されています。

SELECT origin_state, origin_zip, destination_state, sum(package_weight)
FROM shipping
GROUP BY GROUPING SETS (
    (origin_state),
    (origin_state, origin_zip),
    (destination_state));
 origin_state | origin_zip | destination_state | _col0
--------------+------------+-------------------+-------
 New Jersey   | NULL       | NULL              |   225
 California   | NULL       | NULL              |  1397
 New York     | NULL       | NULL              |     3
 California   |      90210 | NULL              |  1337
 California   |      94131 | NULL              |    60
 New Jersey   |       7081 | NULL              |   225
 New York     |      10002 | NULL              |     3
 NULL         | NULL       | Colorado          |     5
 NULL         | NULL       | New Jersey        |    58
 NULL         | NULL       | Connecticut       |  1562
(10 rows)

上記のクエリは、論理的には複数の GROUP BY クエリの UNION ALL と同等と見なすことができます。

SELECT origin_state, NULL, NULL, sum(package_weight)
FROM shipping GROUP BY origin_state

UNION ALL

SELECT origin_state, origin_zip, NULL, sum(package_weight)
FROM shipping GROUP BY origin_state, origin_zip

UNION ALL

SELECT NULL, NULL, destination_state, sum(package_weight)
FROM shipping GROUP BY destination_state;

ただし、複雑なグループ化構文(GROUPING SETSCUBE、または ROLLUP)を使用したクエリは、基になるデータソースを 1 回だけ読み取りますが、UNION ALL を使用したクエリは基になるデータを 3 回読み取ります。そのため、データソースが決定論的でない場合、UNION ALL を使用したクエリは一貫性のない結果を生成する可能性があります。

CUBE

CUBE 演算子は、特定の列セットに対して可能なすべてのグループ化セット(つまり、べき集合)を生成します。たとえば、クエリ

SELECT origin_state, destination_state, sum(package_weight)
FROM shipping
GROUP BY CUBE (origin_state, destination_state);

は以下と同等です。

SELECT origin_state, destination_state, sum(package_weight)
FROM shipping
GROUP BY GROUPING SETS (
    (origin_state, destination_state),
    (origin_state),
    (destination_state),
    ());
 origin_state | destination_state | _col0
--------------+-------------------+-------
 California   | New Jersey        |    55
 California   | Colorado          |     5
 New York     | New Jersey        |     3
 New Jersey   | Connecticut       |   225
 California   | Connecticut       |  1337
 California   | NULL              |  1397
 New York     | NULL              |     3
 New Jersey   | NULL              |   225
 NULL         | New Jersey        |    58
 NULL         | Connecticut       |  1562
 NULL         | Colorado          |     5
 NULL         | NULL              |  1625
(12 rows)

ROLLUP

ROLLUP 演算子は、特定の列セットに対して可能なすべての小計を生成します。たとえば、クエリ

SELECT origin_state, origin_zip, sum(package_weight)
FROM shipping
GROUP BY ROLLUP (origin_state, origin_zip);
 origin_state | origin_zip | _col2
--------------+------------+-------
 California   |      94131 |    60
 California   |      90210 |  1337
 New Jersey   |       7081 |   225
 New York     |      10002 |     3
 California   | NULL       |  1397
 New York     | NULL       |     3
 New Jersey   | NULL       |   225
 NULL         | NULL       |  1625
(8 rows)

は以下と同等です。

SELECT origin_state, origin_zip, sum(package_weight)
FROM shipping
GROUP BY GROUPING SETS ((origin_state, origin_zip), (origin_state), ());

複数のグループ化式の組み合わせ

同じクエリ内の複数のグループ化式は、クロス積のセマンティクスを持つものとして解釈されます。たとえば、次のクエリ

SELECT origin_state, destination_state, origin_zip, sum(package_weight)
FROM shipping
GROUP BY
    GROUPING SETS ((origin_state, destination_state)),
    ROLLUP (origin_zip);

は次のように書き直すことができます。

SELECT origin_state, destination_state, origin_zip, sum(package_weight)
FROM shipping
GROUP BY
    GROUPING SETS ((origin_state, destination_state)),
    GROUPING SETS ((origin_zip), ());

は論理的には以下と同等です。

SELECT origin_state, destination_state, origin_zip, sum(package_weight)
FROM shipping
GROUP BY GROUPING SETS (
    (origin_state, destination_state, origin_zip),
    (origin_state, destination_state));
 origin_state | destination_state | origin_zip | _col3
--------------+-------------------+------------+-------
 New York     | New Jersey        |      10002 |     3
 California   | New Jersey        |      94131 |    55
 New Jersey   | Connecticut       |       7081 |   225
 California   | Connecticut       |      90210 |  1337
 California   | Colorado          |      94131 |     5
 New York     | New Jersey        | NULL       |     3
 New Jersey   | Connecticut       | NULL       |   225
 California   | Colorado          | NULL       |     5
 California   | Connecticut       | NULL       |  1337
 California   | New Jersey        | NULL       |    55
(10 rows)

ALL および DISTINCT 量指定子は、重複するグループ化セットがそれぞれ個別の出力行を生成するかどうかを決定します。これは、同じクエリで複数の複雑なグループ化セットが組み合わされる場合に特に役立ちます。たとえば、次のクエリ

SELECT origin_state, destination_state, origin_zip, sum(package_weight)
FROM shipping
GROUP BY ALL
    CUBE (origin_state, destination_state),
    ROLLUP (origin_state, origin_zip);

は以下と同等です。

SELECT origin_state, destination_state, origin_zip, sum(package_weight)
FROM shipping
GROUP BY GROUPING SETS (
    (origin_state, destination_state, origin_zip),
    (origin_state, origin_zip),
    (origin_state, destination_state, origin_zip),
    (origin_state, origin_zip),
    (origin_state, destination_state),
    (origin_state),
    (origin_state, destination_state),
    (origin_state),
    (origin_state, destination_state),
    (origin_state),
    (destination_state),
    ());

ただし、クエリが GROUP BYDISTINCT 量指定子を使用する場合

SELECT origin_state, destination_state, origin_zip, sum(package_weight)
FROM shipping
GROUP BY DISTINCT
    CUBE (origin_state, destination_state),
    ROLLUP (origin_state, origin_zip);

一意のグループ化セットのみが生成されます。

SELECT origin_state, destination_state, origin_zip, sum(package_weight)
FROM shipping
GROUP BY GROUPING SETS (
    (origin_state, destination_state, origin_zip),
    (origin_state, origin_zip),
    (origin_state, destination_state),
    (origin_state),
    (destination_state),
    ());

デフォルトのセット量指定子は ALL です。

GROUPING 操作

grouping(col1, ..., colN) -> bigint

grouping 操作は、10 進数に変換されたビットセットを返し、グループ化にどの列が存在するかを示します。GROUPING SETSROLLUPCUBE、または GROUP BY と組み合わせて使用する必要があり、その引数は対応する GROUPING SETSROLLUPCUBE、または GROUP BY 句で参照される列と正確に一致する必要があります。

特定の行の結果のビットセットを計算するために、ビットは引数列に割り当てられ、最右端の列が最下位ビットになります。特定のグループ化の場合、対応する列がグループ化に含まれている場合はビットは 0 に設定され、そうでない場合は 1 に設定されます。たとえば、以下のクエリを考えてみましょう。

SELECT origin_state, origin_zip, destination_state, sum(package_weight),
       grouping(origin_state, origin_zip, destination_state)
FROM shipping
GROUP BY GROUPING SETS (
        (origin_state),
        (origin_state, origin_zip),
        (destination_state));
origin_state | origin_zip | destination_state | _col3 | _col4
--------------+------------+-------------------+-------+-------
California   | NULL       | NULL              |  1397 |     3
New Jersey   | NULL       | NULL              |   225 |     3
New York     | NULL       | NULL              |     3 |     3
California   |      94131 | NULL              |    60 |     1
New Jersey   |       7081 | NULL              |   225 |     1
California   |      90210 | NULL              |  1337 |     1
New York     |      10002 | NULL              |     3 |     1
NULL         | NULL       | New Jersey        |    58 |     6
NULL         | NULL       | Connecticut       |  1562 |     6
NULL         | NULL       | Colorado          |     5 |     6
(10 rows)

上記の最初のグループ化には、origin_state 列のみが含まれ、origin_zip 列と destination_state 列は除外されます。そのグループ化のために構築されたビットセットは 011 であり、最上位ビットは origin_state を表します。

HAVING 句

HAVING句は、集約関数およびGROUP BY句と組み合わせて使用​​され、選択されるグループを制御します。 HAVING句は、指定された条件を満たさないグループを除外します。 HAVINGは、グループと集計が計算された後にグループをフィルタリングします。

次の例では、customerテーブルに対してクエリを実行し、指定された値よりも口座残高が大きいグループを選択します。

SELECT count(*), mktsegment, nationkey,
       CAST(sum(acctbal) AS bigint) AS totalbal
FROM customer
GROUP BY mktsegment, nationkey
HAVING sum(acctbal) > 5700000
ORDER BY totalbal DESC;
 _col0 | mktsegment | nationkey | totalbal
-------+------------+-----------+----------
  1272 | AUTOMOBILE |        19 |  5856939
  1253 | FURNITURE  |        14 |  5794887
  1248 | FURNITURE  |         9 |  5784628
  1243 | FURNITURE  |        12 |  5757371
  1231 | HOUSEHOLD  |         3 |  5753216
  1251 | MACHINERY  |         2 |  5719140
  1247 | FURNITURE  |         8 |  5701952
(7 rows)

UNION | INTERSECT | EXCEPT 句

UNIONINTERSECT、およびEXCEPTはすべて集合演算です。これらの句は、複数のSELECTステートメントの結果を単一の結果セットに結合するために使用されます。

query UNION [ALL | DISTINCT] query
query INTERSECT [DISTINCT] query
query EXCEPT [DISTINCT] query

引数ALLまたはDISTINCTは、最終結果セットにどの行が含まれるかを制御します。引数ALLが指定されている場合、行が同一であってもすべての行が含まれます。引数DISTINCTが指定されている場合、一意の行のみが結合された結果セットに含まれます。どちらも指定されていない場合、動作はデフォルトでDISTINCTになります。 ALL引数は、INTERSECTまたはEXCEPTではサポートされていません。

複数の集合演算は、括弧によって順序が明示的に指定されていない限り、左から右に処理されます。さらに、INTERSECTEXCEPTおよびUNIONよりも強く結合します。つまり、A UNION B INTERSECT C EXCEPT DA UNION (B INTERSECT C) EXCEPT Dと同じです。

UNION

UNIONは、最初のクエリの結果セットにあるすべての行と、2番目のクエリの結果セットにある行を結合します。以下は、最も単純なUNION句の例の1つです。値13を選択し、この結果セットを値42を選択する2番目のクエリと結合します。

SELECT 13
UNION
SELECT 42;
 _col0
-------
    13
    42
(2 rows)

次のクエリは、UNIONUNION ALLの違いを示しています。値13を選択し、この結果セットを値4213を選択する2番目のクエリと結合します。

SELECT 13
UNION
SELECT * FROM (VALUES 42, 13);
 _col0
-------
    13
    42
(2 rows)
SELECT 13
UNION ALL
SELECT * FROM (VALUES 42, 13);
 _col0
-------
    13
    42
    13
(2 rows)

INTERSECT

INTERSECTは、最初と2番目のクエリの両方の結果セットにある行のみを返します。以下は、最も単純なINTERSECT句の例の1つです。値1342を選択し、この結果セットを値13を選択する2番目のクエリと結合します。 42は最初のクエリの結果セットにのみ存在するため、最終結果には含まれません。

SELECT * FROM (VALUES 13, 42)
INTERSECT
SELECT 13;
 _col0
-------
    13
(2 rows)

EXCEPT

EXCEPTは、最初のクエリの結果セットにはあるが、2番目のクエリの結果セットにはない行を返します。以下は、最も単純なEXCEPT句の例の1つです。値1342を選択し、この結果セットを値13を選択する2番目のクエリと結合します。 13は2番目のクエリの結果セットにも存在するため、最終結果には含まれません。

SELECT * FROM (VALUES 13, 42)
EXCEPT
SELECT 13;
 _col0
-------
   42
(2 rows)

ORDER BY 句

ORDER BY句は、結果セットを1つ以上の出力式でソートするために使用されます。

ORDER BY expression [ ASC | DESC ] [ NULLS { FIRST | LAST } ] [, ...]

各式は出力列で構成されている場合もあれば、1から始まる位置で出力列を選択する序数である場合もあります。 ORDER BY句は、GROUP BY句またはHAVING句の後、OFFSETLIMIT、またはFETCH FIRST句の前に評価されます。デフォルトのNULL順序は、順序方向に関係なく、NULLS LASTです。

OFFSET 句

OFFSET句は、結果セットから先頭の行を指定された数だけ破棄するために使用されます。

OFFSET count [ ROW | ROWS ]

ORDER BY句が存在する場合、OFFSET句はソートされた結果セットに対して評価され、先頭の行が破棄された後もセットはソートされたままになります。

SELECT name FROM nation ORDER BY name OFFSET 22;
      name
----------------
 UNITED KINGDOM
 UNITED STATES
 VIETNAM
(3 rows)

それ以外の場合、どの行が破棄されるかは任意です。 OFFSET句で指定されたカウントが結果セットのサイズ以上の場合、最終結果は空になります。

LIMIT 句

LIMIT句は、結果セットの行数を制限します。 LIMIT ALLは、LIMIT句を省略するのと同じです。

LIMIT { count | ALL }

次の例では、大きなテーブルに対してクエリを実行しますが、LIMIT句により、出力は5行のみに制限されます(クエリにORDER BYがないため、どの行が返されるかは任意です)。

SELECT orderdate FROM orders LIMIT 5;
 o_orderdate
-------------
 1996-04-14
 1992-01-15
 1995-02-01
 1995-11-12
 1992-04-26
(5 rows)

LIMIT ALLは、LIMIT句を省略するのと同じです。

OFFSET句が存在する場合、LIMIT句はOFFSET句の後に評価されます。

SELECT * FROM (VALUES 5, 2, 4, 1, 3) t(x) ORDER BY x OFFSET 2 LIMIT 2;
 x
---
 3
 4
(2 rows)

TABLESAMPLE

複数のサンプリング方法があります。

BERNOULLI

各行は、サンプルの割合の確率でテーブルサンプルに選択されます。 Bernoulliメソッドを使用してテーブルをサンプリングする場合、テーブルのすべての物理ブロックがスキャンされ、特定の行がスキップされます(サンプルの割合と実行時に計算されたランダム値の比較に基づく)。

行が結果に含まれる確率は、他の行とは無関係です。これは、サンプリングされたテーブルをディスクから読み取るために必要な時間を短縮しません。サンプリングされた出力がさらに処理される場合、クエリ全体の時間に影響を与える可能性があります。

SYSTEM

このサンプリング方法は、テーブルを論理的なデータセグメントに分割し、この粒度でテーブルをサンプリングします。このサンプリング方法は、特定のデータセグメントからすべての行を選択するか、スキップします(サンプルの割合と実行時に計算されたランダム値の比較に基づく)。

システムサンプリングで選択される行は、どのコネクタが使用されるかによって異なります。たとえば、Hiveで使用する場合、データがHDFSにどのように配置されているかによって異なります。この方法は、独立したサンプリング確率を保証しません。

注記

2つの方法のどちらも、返される行数の確定的な境界を許可しません。

SELECT *
FROM users TABLESAMPLE BERNOULLI (50);

SELECT *
FROM users TABLESAMPLE SYSTEM (75);

結合でのサンプリングの使用

SELECT o.*, i.*
FROM orders o TABLESAMPLE SYSTEM (10)
JOIN lineitem i TABLESAMPLE BERNOULLI (40)
  ON o.orderkey = i.orderkey;

UNNEST

UNNESTは、ARRAYまたはMAPをリレーションに展開するために使用できます。配列は単一の列に展開され、マップは2つの列(キー、値)に展開されます。 UNNESTは複数の引数で使用することもでき、その場合、それらは複数の列に展開され、カーディナリティが最も高い引数と同じ数の行になります(他の列はNULLで埋められます)。 UNNESTにはオプションでWITH ORDINALITY句を含めることができ、その場合、追加の序数列が最後に追加されます。 UNNESTは通常JOINで使用され、結合の左側のリレーションの列を参照できます。

単一の配列列の使用

SELECT student, score
FROM tests
CROSS JOIN UNNEST(scores) AS t (score);

複数の配列列の使用

SELECT numbers, animals, n, a
FROM (
  VALUES
    (ARRAY[2, 5], ARRAY['dog', 'cat', 'bird']),
    (ARRAY[7, 8, 9], ARRAY['cow', 'pig'])
) AS x (numbers, animals)
CROSS JOIN UNNEST(numbers, animals) AS t (n, a);
  numbers  |     animals      |  n   |  a
-----------+------------------+------+------
 [2, 5]    | [dog, cat, bird] |    2 | dog
 [2, 5]    | [dog, cat, bird] |    5 | cat
 [2, 5]    | [dog, cat, bird] | NULL | bird
 [7, 8, 9] | [cow, pig]       |    7 | cow
 [7, 8, 9] | [cow, pig]       |    8 | pig
 [7, 8, 9] | [cow, pig]       |    9 | NULL
(6 rows)

WITH ORDINALITY

SELECT numbers, n, a
FROM (
  VALUES
    (ARRAY[2, 5]),
    (ARRAY[7, 8, 9])
) AS x (numbers)
CROSS JOIN UNNEST(numbers) WITH ORDINALITY AS t (n, a);
  numbers  | n | a
-----------+---+---
 [2, 5]    | 2 | 1
 [2, 5]    | 5 | 2
 [7, 8, 9] | 7 | 1
 [7, 8, 9] | 8 | 2
 [7, 8, 9] | 9 | 3
(5 rows)

単一のマップ列の使用

SELECT
    animals, a, n
FROM (
    VALUES
        (MAP(ARRAY['dog', 'cat', 'bird'], ARRAY[1, 2, 0])),
        (MAP(ARRAY['dog', 'cat'], ARRAY[4, 5]))
) AS x (animals)
CROSS JOIN UNNEST(animals) AS t (a, n);
           animals          |  a   | n
----------------------------+------+---
 {"cat":2,"bird":0,"dog":1} | dog  | 1
 {"cat":2,"bird":0,"dog":1} | cat  | 2
 {"cat":2,"bird":0,"dog":1} | bird | 0
 {"cat":5,"dog":4}          | dog  | 4
 {"cat":5,"dog":4}          | cat  | 5
(5 rows)

結合

結合を使用すると、複数のリレーションからのデータを結合できます。

CROSS JOIN

クロス結合は、2つのリレーションのデカルト積(すべての組み合わせ)を返します。クロス結合は、明示的なCROSS JOIN構文を使用するか、FROM句で複数のリレーションを指定することによって指定できます。

次の両方のクエリは同等です。

SELECT *
FROM nation
CROSS JOIN region;

SELECT *
FROM nation, region;

nation テーブルには25行、region テーブルには5行が含まれているため、2つのテーブルのクロス結合は125行を生成します。

SELECT n.name AS nation, r.name AS region
FROM nation AS n
CROSS JOIN region AS r
ORDER BY 1, 2;
     nation     |   region
----------------+-------------
 ALGERIA        | AFRICA
 ALGERIA        | AMERICA
 ALGERIA        | ASIA
 ALGERIA        | EUROPE
 ALGERIA        | MIDDLE EAST
 ARGENTINA      | AFRICA
 ARGENTINA      | AMERICA
...
(125 rows)

列名の修飾

結合における2つのリレーションに同じ名前の列がある場合、列参照は、リレーションのエイリアス(リレーションにエイリアスがある場合)またはリレーション名を使用して修飾する必要があります。

SELECT nation.name, region.name
FROM nation
CROSS JOIN region;

SELECT n.name, r.name
FROM nation AS n
CROSS JOIN region AS r;

SELECT n.name, r.name
FROM nation n
CROSS JOIN region r;

以下のクエリは、Column 'name' is ambiguous というエラーで失敗します。

SELECT name
FROM nation
CROSS JOIN region;

USING句

USING 句を使用すると、結合する両方のテーブルに結合キーと同じ名前がある場合、より短いクエリを作成できます。

例えば

SELECT *
FROM table_1
JOIN table_2
ON table_1.key_A = table_2.key_A AND table_1.key_B = table_2.key_B

は以下のように書き直すことができます。

SELECT *
FROM table_1
JOIN table_2
USING (key_A, key_B)

USING を使用した JOIN の出力は、結合キー列(上記の例では key_Akey_B)のコピー1つと、それに続いて table_1 の残りの列、そして table_2 の残りの列となります。結合キーは、クエリ内でそれらを参照する目的で、元のテーブルの列リストには含まれないことに注意してください。テーブルプレフィックスを使用してアクセスすることはできず、SELECT table_1.*, table_2.* を実行した場合、結合列は出力に含まれません。

以下の2つのクエリは同等です。

SELECT *
FROM (
    VALUES
        (1, 3, 10),
        (2, 4, 20)
) AS table_1 (key_A, key_B, y1)
LEFT JOIN (
    VALUES
        (1, 3, 100),
        (2, 4, 200)
) AS table_2 (key_A, key_B, y2)
USING (key_A, key_B)

-----------------------------

SELECT key_A, key_B, table_1.*, table_2.*
FROM (
    VALUES
        (1, 3, 10),
        (2, 4, 20)
) AS table_1 (key_A, key_B, y1)
LEFT JOIN (
    VALUES
        (1, 3, 100),
        (2, 4, 200)
) AS table_2 (key_A, key_B, y2)
USING (key_A, key_B)

そして、以下の出力を生成します。

 key_A | key_B | y1 | y2
-------+-------+----+-----
     1 |     3 | 10 | 100
     2 |     4 | 20 | 200
(2 rows)

サブクエリ

サブクエリは、クエリで構成される式です。サブクエリは、サブクエリ外の列を参照する場合、相関サブクエリとなります。論理的には、サブクエリは、周囲のクエリの各行に対して評価されます。したがって、参照される列は、サブクエリの単一の評価中は定数になります。

注記

相関サブクエリのサポートは限定的です。すべての標準形式がサポートされているわけではありません。

EXISTS述語

EXISTS 述語は、サブクエリが行を返すかどうかを判断します。

SELECT name
FROM nation
WHERE EXISTS (SELECT * FROM region WHERE region.regionkey = nation.regionkey)

IN述語

IN 述語は、サブクエリによって生成された値が指定された式と等しいかどうかを判断します。IN の結果は、NULLに関する標準ルールに従います。サブクエリは、正確に1つの列を生成する必要があります。

SELECT name
FROM nation
WHERE regionkey IN (SELECT regionkey FROM region)

スカラサブクエリ

スカラサブクエリは、0行または1行を返す非相関サブクエリです。サブクエリが複数の行を生成するのはエラーです。サブクエリが行を生成しない場合、戻り値は NULL です。

SELECT name
FROM nation
WHERE regionkey = (SELECT max(regionkey) FROM region)

注記

現在、スカラサブクエリからは単一の列のみを返すことができます。