표준 SQL 쿼리 구문

쿼리 문은 테이블 또는 표현식을 한 개 이상 스캔하고 계산된 결과 행을 반환합니다. 여기서는 BigQuery의 SQL 쿼리에 관한 구문을 설명합니다.

SQL 구문

query_statement:
    [ WITH with_query_name AS ( query_expr ) [, ...] ]
query_expr 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. ]* [ EXCEPT ( column_name [, ...] ) ]
[ REPLACE ( expression [ AS ] column_name [, ...] ) ]
| expression [ [ AS ] alias ] } [, ...] [ FROM from_item [, ...] ] [ WHERE bool_expression ] [ GROUP BY { expression [, ...] | ROLLUP ( expression [, ...] ) } ] [ HAVING bool_expression ] [ WINDOW window_name AS ( window_definition ) [, ...] ] set_op: UNION { ALL | DISTINCT } | INTERSECT DISTINCT | EXCEPT DISTINCT from_item: { table_name [ [ AS ] alias ] [ FOR SYSTEM TIME AS OF timestamp_expression ] | join | ( query_expr ) [ [ AS ] alias ] | field_path | { UNNEST( array_expression ) | UNNEST( array_path ) | array_path } [ [ AS ] alias ] [ WITH OFFSET [ [ AS ] alias ] ] | with_query_name [ [ AS ] alias ] } join: from_item [ join_type ] JOIN from_item [ { ON bool_expression | USING ( join_column [, ...] ) } ] join_type: { INNER | CROSS | FULL [OUTER] | LEFT [OUTER] | RIGHT [OUTER] }

표기법:

  • 대괄호 '[ ]'는 절(선택사항)을 의미합니다.
  • 괄호 '( )'는 리터럴 괄호를 의미합니다.
  • 세로 막대 '|'는 논리 OR을 의미합니다.
  • 중괄호 '{ }'는 옵션 조합을 묶는 데 사용됩니다.
  • 꺾쇠 괄호 '[, ...]' 안에 있는 쉼표 다음에 오는 줄임표는 앞의 항목이 쉼표로 구분된 목록으로 반복될 수 있음을 나타냅니다.

SELECT 목록

구문:

SELECT  [{ ALL | DISTINCT }]
    { [ expression. ]* [ EXCEPT ( column_name [, ...] ) ]
[ REPLACE ( expression [ AS ] column_name [, ...] ) ]
| expression [ [ AS ] alias ] } [, ...]

SELECT 목록은 쿼리가 반환할 열을 정의합니다. SELECT 목록의 표현식은 해당 FROM 절에 있는 from_item의 모든 열을 참조할 수 있습니다.

SELECT 목록의 각 항목은 다음 중 하나입니다.

  • *
  • expression
  • expression.*

SELECT *

SELECT *(종종 select star라고도 함)는 전체 쿼리를 실행한 후에 표시되는 각 열에 대해 출력 열 한 개를 생성합니다.

SELECT * FROM (SELECT "apple" AS fruit, "carrot" AS vegetable);

+-------+-----------+
| fruit | vegetable |
+-------+-----------+
| apple | carrot    |
+-------+-----------+

SELECT expression

SELECT 목록의 항목은 표현식일 수 있습니다. 표현식은 단일 값으로 평가되며 명시적 alias(선택사항)가 있는 출력 열 한 개를 생성합니다.

표현식에 명시적 별칭이 없는 경우, 가능하면 암시적 별칭 규칙에 따라 암시적 별칭을 수신합니다. 그 밖의 경우 열은 익명이며, 이름을 쿼리의 다른 곳에서 참조할 수 없습니다.

SELECT expression.*

SELECT 목록의 항목은 expression.* 형식을 취할 수도 있습니다. 그러면 expression의 각 열 또는 최상위 필드에 대해 출력 열 한 개가 생성됩니다. 이 표현식은 테이블 별칭이거나 STRUCT와 같은 필드가 있는 데이터 유형의 단일 값으로 평가되어야 합니다.

다음 쿼리는 groceries 테이블의 각 열에 대해 출력 열 한 개를 생성하며 g로 별칭이 지정됩니다.

WITH groceries AS
  (SELECT "milk" AS dairy,
   "eggs" AS protein,
   "bread" AS grain)
SELECT g.*
FROM groceries AS g;

+-------+---------+-------+
| dairy | protein | grain |
+-------+---------+-------+
| milk  | eggs    | bread |
+-------+---------+-------+

기타 예:

WITH locations AS
  (SELECT STRUCT("Seattle" AS city, "Washington" AS state) AS location
  UNION ALL
  SELECT STRUCT("Phoenix" AS city, "Arizona" AS state) AS location)
SELECT l.location.*
FROM locations l;

+---------+------------+
| city    | state      |
+---------+------------+
| Seattle | Washington |
| Phoenix | Arizona    |
+---------+------------+
WITH locations AS
  (SELECT ARRAY<STRUCT<city STRING, state STRING>>[("Seattle", "Washington"),
    ("Phoenix", "Arizona")] AS location)
SELECT l.LOCATION[offset(0)].*
FROM locations l;

+---------+------------+
| city    | state      |
+---------+------------+
| Seattle | Washington |
+---------+------------+

SELECT 수정자

다음과 같이 SELECT 쿼리에서 반환된 결과를 수정할 수 있습니다.

SELECT DISTINCT

SELECT DISTINCT 문은 중복 행을 삭제하고 나머지 행만 반환합니다. SELECT DISTINCT는 다음 유형의 열을 반환할 수 없습니다.

  • STRUCT
  • ARRAY

SELECT * EXCEPT

SELECT * EXCEPT 문은 결과에서 제외할 열의 이름을 한 개 이상 지정합니다. 일치하는 모든 열 이름은 출력에서 생략됩니다.

WITH orders AS
  (SELECT 5 as order_id,
  "sprocket" as item_name,
  200 as quantity)
SELECT * EXCEPT (order_id)
FROM orders;

+-----------+----------+
| item_name | quantity |
+-----------+----------+
| sprocket  | 200      |
+-----------+----------+

참고: SELECT * EXCEPT는 이름이 없는 열을 제외하지 않습니다.

SELECT * REPLACE

SELECT * REPLACE 문은 expression AS identifier 절을 한 개 이상 지정합니다. 각 식별자는 SELECT * 문의 열 이름 한 개와 일치해야 합니다. 출력 열 목록에서 REPLACE 절의 식별자와 일치하는 열은 해당 REPLACE 절의 표현식으로 대체됩니다.

SELECT * REPLACE 문은 열의 이름 또는 순서를 변경하지 않습니다. 그러나 값과 값 유형을 변경할 수 있습니다.

WITH orders AS
  (SELECT 5 as order_id,
  "sprocket" as item_name,
  200 as quantity)
SELECT * REPLACE ("widget" AS item_name)
FROM orders;

+----------+-----------+----------+
| order_id | item_name | quantity |
+----------+-----------+----------+
| 5        | widget    | 200      |
+----------+-----------+----------+

WITH orders AS
  (SELECT 5 as order_id,
  "sprocket" as item_name,
  200 as quantity)
SELECT * REPLACE (quantity/2 AS quantity)
FROM orders;

+----------+-----------+----------+
| order_id | item_name | quantity |
+----------+-----------+----------+
| 5        | sprocket  | 100      |
+----------+-----------+----------+

참고: SELECT * REPLACE는 이름이 없는 열을 대체하지 않습니다.

SELECT ALL

SELECT ALL 문은 중복 행을 포함한 모든 행을 반환합니다. SELECT ALLSELECT의 기본 동작입니다.

별칭

SELECT 목록 별칭의 구문과 공개에 대해서는 별칭을 참조하세요.

분석 함수

분석 함수와 관련된 절은 다른 문서에서 설명합니다.

  • OVER 절과 PARTITION BY: 분석 함수를 참조하세요.

  • WINDOW 절과 윈도우 함수: WINDOW 절을 참조하세요.

FROM 절

FROM 절은 행을 검색할 테이블을 표시하고 나머지 쿼리에서 처리할 단일 행 스트림을 생성하기 위해 해당 행을 조인하는 방법을 지정합니다.

구문

from_item: {
    table_name [ [ AS ] alias ] [ FOR SYSTEM TIME AS OF timestamp_expression ]  |
    join |
    ( query_expr ) [ [ AS ] alias ] |
    field_path |
    { UNNEST( array_expression ) | UNNEST( array_path ) | array_path }
        [ [ AS ] alias ] [ WITH OFFSET [ [ AS ] alias ] ] |
    with_query_name [ [ AS ] alias ]
}

table_name

기존 테이블 이름입니다(선택적으로 정규화됨).

SELECT * FROM Roster;
SELECT * FROM dataset.Roster;
SELECT * FROM project.dataset.Roster;

FOR SYSTEM TIME AS OF

FOR SYSTEM TIME AS OF는 테이블 정의의 이전 버전과 timestamp_expression에 있었던 행을 참조합니다.

제한사항:

FOR SYSTEM TIME AS OF를 포함한 FROM 절의 소스 테이블은 다음 중 하나가 아니어야 합니다.

  • 평면화된 배열 또는 UNNEST 연산자 출력을 포함한 ARRAY 스캔
  • WITH 절에서 정의된 공통 테이블 표현식

timestamp_expression은 상수 표현식이어야 합니다. 여기에는 다음이 포함될 수 없습니다.

  • 하위 쿼리
  • 상호 관련된 참조(SELECT 목록처럼 더 높은 수준의 쿼리 문에 나타나는 테이블의 열 참조)

  • 사용자 정의 함수(UDF)

timestamp_expression 값은 다음 범위에 속할 수 없습니다.

  • 현재 타임스탬프 이후(미래)
  • 현재 타임스탬프로부터 7일 이상 이전

단일 쿼리 문은 현재 시점을 포함하여 하나 이상의 시점에서 단일 테이블을 참조할 수 없습니다. 즉, 쿼리는 동일한 타임스탬프에서 테이블을 여러 번 참조할 수 있지만 현재 버전과 이전 버전 또는 두 가지 이전 버전을 참조할 수 없습니다.

예:

다음 쿼리는 한 시간 전부터 이전 테이블의 표를 반환합니다.

SELECT *
FROM t
  FOR SYSTEM TIME AS OF TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 1 HOUR);

다음 쿼리는 절대적 시점에서 이전 버전의 테이블을 반환합니다.

SELECT *
FROM t
  FOR SYSTEM TIME AS OF '2017-01-01 10:00:00-07:00';

timestamp_expression에 포함 쿼리 열과 상호 관련된 참조가 포함되어 있으므로, 다음 쿼리는 오류를 반환합니다.

SELECT *
FROM t1
WHERE t1.a IN (SELECT t2.a
               FROM t2 FOR SYSTEM TIME AS OF t1.timestamp_column);

join

아래 JOIN 유형을 참조하세요.

select

( select ) [ [ AS ] alias ]는 테이블 하위 쿼리입니다.

field_path

FROM 절에서 field_path는 데이터 유형 내에서 필드로 해석되는 경로입니다. field_path는 중첩된 데이터 구조에서 임의의 깊이까지 들어갈 수 있습니다.

유효한 field_path 값에 대한 예는 다음과 같습니다.

SELECT * FROM T1 t1, t1.array_column;

SELECT * FROM T1 t1, t1.struct_column.array_field;

SELECT (SELECT ARRAY_AGG(c) FROM t1.array_column c) FROM T1 t1;

SELECT a.struct_field1 FROM T1 t1, t1.array_of_structs a;

SELECT (SELECT STRING_AGG(a.struct_field1) FROM t1.array_of_structs a) FROM T1 t1;

FROM 절의 필드 경로는 배열 필드에서 끝나야 합니다. 또한 필드 경로는 경로 끝 앞에 배열을 포함할 수 없습니다. 예를 들어, array_column.some_array.some_array_field 경로는 경로 끝 앞에 배열을 포함하고 있으므로 유효하지 않습니다.

참고: 경로에 이름이 하나만 있으면 경로는 테이블로 해석됩니다. 이 문제를 해결하려면 UNNEST를 사용하여 경로를 래핑하거나 정규화된 경로를 사용합니다.

UNNEST

UNNEST 연산자는 ARRAY를 가져오고 ARRAY의 각 요소에 대해 행 한 개를 만들어 테이블을 반환합니다. 또한 IN 연산자FROM 절 밖에서 UNNEST를 사용할 수 있습니다.

대부분의 요소 유형의 입력 ARRAY의 경우 일반적으로 UNNEST 출력에는 열이 한 개 있습니다. 이 단일 열에는 alias 선택사항이 있어, 쿼리의 다른 위치에서 열을 참조할 때 사용할 수 있습니다. 이러한 요소 유형을 사용하는 ARRAYS는 여러 열을 반환합니다.

  • STRUCT

UNNEST는 입력 ARRAY에서 요소의 순서를 파괴합니다. 선택사항인 WITH OFFSET 절을 사용하여 배열 요소 색인을 포함한 두 번째 열을 반환할 수 있습니다(아래 참조).

STRUCT의 입력 ARRAY의 경우, UNNESTSTRUCT의 각 필드에 대해 별도의 열을 만들고 각 STRUCT의 행 한 개를 반환합니다. 각 열의 별칭은 해당 STRUCT 필드의 이름입니다.

SELECT *
FROM UNNEST(ARRAY<STRUCT<x INT64, y STRING>>[(1, 'foo'), (3, 'bar')]);

+---+-----+
| x | y   |
+---+-----+
| 3 | bar |
| 1 | foo |
+---+-----+

UNNEST 연산자는 값 테이블을 반환하므로, UNNEST의 별칭을 지정하여 쿼리의 다른 위치에서 참조할 수 있는 범위 변수를 정의할 수 있습니다. SELECT 목록에서 범위 변수를 참조하는 경우 쿼리는 입력 테이블에서 원래 STRUCT의 모든 필드를 포함하는 STRUCT를 반환합니다.

SELECT *, struct_value
FROM UNNEST(ARRAY<STRUCT<x INT64, y STRING>>[(1, 'foo'), (3, 'bar')])
       AS struct_value;

+---+-----+--------------+
| x | y   | struct_value |
+---+-----+--------------+
| 3 | bar | {3, bar}     |
| 1 | foo | {1, foo}     |
+---+-----+--------------+

ARRAY 중첩 해제는 명시적이거나 암시적일 수 있습니다. 명시적 중첩 해제에서 array_expression은 ARRAY 값을 반환해야 하지만 ARRAY로 해석될 필요는 없으며, UNNEST 키워드가 필요합니다.

예:

SELECT * FROM UNNEST ([1, 2, 3]);

암시적 중첩 해제에서 array_path는 ARRAY로 해석되어야 하며 UNNEST 키워드는 선택사항입니다.

예:

SELECT x
FROM mytable AS t,
  t.struct_typed_column.array_typed_field1 AS x;

이 시나리오에서 array_path는 임의의 데이터 구조 깊이까지 들어갈 수 있지만 마지막 필드는 ARRAY 유형이어야 합니다. ARRAY에서 명명된 필드를 추출할 수 없으므로 표현식의 이전 필드는 ARRAY 유형일 수 없습니다.

UNNEST는 NULL을 다음과 같이 처리합니다.

  • NULL과 빈 ARRAY는 0개의 행을 생성합니다.
  • NULL을 포함하는 ARRAY는 NULL 값을 포함하는 행을 생성합니다.

선택사항인 WITH OFFSET 절은 UNNEST 연산으로 생성된 각 행의 'offset' 값(즉, 카운트가 0에서 시작)을 포함하는 별도의 열을 반환합니다. 이 열에는 alias 선택사항이 있고, 기본 별칭은 offset입니다.

예:

SELECT * FROM UNNEST ( ) WITH OFFSET AS num;

생성, 결합, 필터링을 포함한 UNNEST를 사용하는 보다 다양한 방법은 Arrays topic을 참조하세요.

with_query_name

WITH 절의 쿼리 이름(WITH 절 참조)은 FROM 절의 어떤 위치에서도 참조할 수 있는 임시 테이블 이름과 같은 역할을 합니다. 아래 예에서 subQ1subQ2with_query_names입니다.

예:

WITH
  subQ1 AS (SELECT * FROM Roster WHERE SchoolID = 52),
  subQ2 AS (SELECT SchoolID FROM subQ1)
SELECT DISTINCT * FROM subQ2;

사용자가 테이블 이름을 한정하지 않는 한 WITH 절은 쿼리 기간 동안 동일한 이름을 가진 영구 테이블을 숨깁니다(예: dataset.Roster 또는 project.dataset.Roster).

하위 쿼리

하위 쿼리는 다른 문 안에 표시되고 괄호 안에 작성되는 쿼리입니다. 하위 쿼리는 '하위 SELECT' 또는 '중첩된 SELECT'라고도 합니다. 전체 SELECT 구문이 하위 쿼리에서 유효합니다.

하위 쿼리에는 두 가지 유형이 있습니다.

  • 표현식 하위 쿼리: 표현식이 유효한 모든 쿼리에서 사용할 수 있습니다. 표현식 하위 쿼리는 단일 값을 반환합니다.
  • 테이블 하위 쿼리: 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 | USING ( join_column [, ...] ) ]

join_type:
    { INNER | CROSS | FULL [OUTER] | LEFT [OUTER] | RIGHT [OUTER] }

JOIN 절은 SELECT 절이 from_item 두 개를 하나의 소스로 쿼리할 수 있도록 이를 병합합니다. join_typeON 또는 USING 절('조인 조건')은 단일 소스를 구성하기 위해 두 from_item의 행을 결합하고 삭제할 방법을 지정합니다.

모든 JOIN 절에 join_type이 있어야 합니다.

다음 조건 중 하나가 true인 경우를 제외하고 JOIN 절에 조인 조건이 필요합니다.

  • join_typeCROSS입니다.
  • from_item의 하나 또는 둘 모두 테이블이 아닙니다(예: array_path 또는 field_path).

[INNER] JOIN

INNER JOIN(또는 간단히 JOIN)은 두 from_item의 카티전 곱을 효과적으로 계산하며 조인 조건을 충족하지 않는 모든 행을 삭제합니다. '효과적으로'라는 의미는 실제로 카티전 곱을 계산하지 않고 INNER JOIN을 구현할 수 있음을 나타냅니다.

CROSS JOIN

CROSS JOIN은 두 from_item의 카티전 곱을 반환합니다. 다시 말해, 두 from_item의 모든 행을 유지하고 첫 번째 from_item의 각 행을 두 번째 from_item의 각 행에 결합합니다.

쉼표 교차 조인

CROSS JOINfrom_item을 구분하기 위한 쉼표를 사용하여 명시적으로(바로 위 내용 참조) 또는 암시적으로 작성될 수 있습니다.

암시적 '쉼표 교차 조인'의 예:

SELECT * FROM Roster, TeamMascot;

다음은 명시적 교차 조인에 해당합니다.

SELECT * FROM Roster CROSS JOIN TeamMascot;

괄호 안에 쉼표 교차 조인을 작성할 수 없습니다.

잘못된 괄호 안의 쉼표 교차 조인:

SELECT * FROM t CROSS JOIN (Roster, TeamMascot);  // INVALID.

JOIN 시퀀스에서 쉼표 교차 조인의 작동 방식에 대한 자세한 내용은 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

오른쪽 from_item의 행이 조인 조건을 충족하지 않는 경우에도 두 from_item에 대한 LEFT OUTER JOIN(또는 간단히 LEFT JOIN) 결과는 항상 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이 포함됩니다. bool_expression이 TRUE를 반환하면 결합된 행(두 행을 조인한 결과)은 조인 조건을 충족합니다.

예:

SELECT * FROM Roster INNER JOIN PlayerStats
ON Roster.LastName = PlayerStats.LastName;

USING 절

USING 절에는 두 입력 테이블 모두에서 발생하는 한 개 이상의 열의 column_list가 필요합니다. 이 절은 해당 열에서 동등 비교를 수행하고 동등 비교가 TRUE를 반환하면 행은 조인 조건을 충족합니다.

대부분의 경우, USING 키워드를 사용하는 문은 ON 키워드를 사용하는 문과 같습니다. 다음 문을 예로 들어보겠습니다.

SELECT FirstName
FROM Roster INNER JOIN PlayerStats
USING (LastName);

위 항목은 다음과 동일합니다.

SELECT FirstName
FROM Roster INNER JOIN PlayerStats
ON Roster.LastName = PlayerStats.LastName;

USING을 사용한 쿼리 결과는 SELECT * 사용 시 ON을 사용하는 쿼리와 다릅니다. 이를 설명하기 위해 다음 쿼리를 살펴보겠습니다.

SELECT * FROM Roster INNER JOIN PlayerStats
USING (LastName);

이 문은 RosterPlayerStats의 행을 반환합니다. 여기서 Roster.LastNamePlayerStats.LastName과 동일합니다. 결과에는 단일 LastName 열이 포함됩니다.

반대로 다음 쿼리를 살펴보겠습니다.

SELECT * FROM Roster INNER JOIN PlayerStats
ON Roster.LastName = PlayerStats.LastName;

이 문은 RosterPlayerStats의 행을 반환합니다. 여기서 Roster.LastNamePlayerStats.LastName과 동일합니다. 결과에는 Roster에서 하나, PlayerStats에서 하나씩 LastName 열이 총 두 개 포함됩니다.

JOIN 시퀀스

FROM 절에는 여러 JOIN 절이 순차적으로 포함될 수 있습니다.

예:

SELECT * FROM a LEFT JOIN b ON TRUE LEFT JOIN c ON TRUE;

여기서 a, b, c는 임의의 from_item입니다. JOIN은 왼쪽에서 오른쪽으로 바인딩되지만, 괄호를 삽입하여 다른 순서로 JOIN을 그룹화할 수 있습니다.

다음 쿼리를 살펴보겠습니다. A(괄호 없음)와 B(괄호 포함)는 서로 동일하지만 C와는 다릅니다. 굵게 표시된 FULL JOIN이 먼저 바인딩됩니다.

A.

SELECT * FROM Roster FULL JOIN TeamMascot USING (SchoolID)
FULL JOIN PlayerStats USING (LastName);

B.

SELECT * FROM ( (Roster FULL JOIN TeamMascot USING (SchoolID))
FULL JOIN PlayerStats USING (LastName));

C.

SELECT * FROM (Roster FULL JOIN (TeamMascot FULL JOIN PlayerStats USING
(LastName)) USING (SchoolID)) ;

JOIN 시퀀스를 포함한 쿼리에 쉼표 교차 조인이 있는 경우 다른 JOIN 유형과 마찬가지로 왼쪽에서 오른쪽으로 그룹화됩니다.

예:

SELECT * FROM a JOIN b ON TRUE, b JOIN c ON TRUE;

위의 쿼리는 다음과 같습니다.

SELECT * FROM ((a JOIN b ON TRUE) CROSS JOIN b) JOIN c ON TRUE);

쉼표 조인 다음에는 RIGHT JOIN 또는 FULL JOIN이 올 수 없습니다.

쉼표 교차 조인 후 잘못된 RIGHT JOIN:

SELECT * FROM Roster, TeamMascot RIGHT JOIN PlayerStats ON TRUE;  // INVALID.

WHERE 절

구문

WHERE bool_expression

WHERE 절은 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 목록의 열 별칭을 참조할 수 없습니다.

INNER JOIN 표현식은 WHERE 절에서 동일한 표현식을 가집니다. 예를 들어, INNER JOINON을 사용하는 쿼리에는 CROSS JOINWHERE를 사용하는 동일한 표현식이 있습니다.

예:

SELECT * FROM Roster INNER JOIN TeamMascot
ON Roster.SchoolID = TeamMascot.SchoolID;

위 항목은 다음과 동일합니다.

SELECT * FROM Roster CROSS JOIN TeamMascot
WHERE Roster.SchoolID = TeamMascot.SchoolID;

GROUP BY 절

구문

GROUP BY { expression [, ...] | ROLLUP ( expression [, ...] ) }

GROUP BY 절은 GROUP BY 절의 expression에서 구분되지 않는 값을 포함한 테이블의 행을 그룹화합니다. expression에 구분되지 않는 값을 갖는 소스 테이블이 여러 행인 경우 GROUP BY 절은 결합된 단일 행을 생성합니다. GROUP BY는 집계 함수가 SELECT 목록에 있거나 출력의 중복성을 제거할 때 주로 사용됩니다. expression의 데이터 유형은 groupable이어야 합니다.

예:

SELECT SUM(PointsScored), LastName
FROM PlayerStats
GROUP BY LastName;

GROUP BY 절은 SELECT 목록의 표현식 이름을 참조할 수 있습니다. 또한 GROUP BY 절은 정수 값을 사용하여 SELECT 목록의 표현식에 대한 서수 참조도 허용합니다. 1SELECT 목록의 첫 번째 표현식을 참조하고, 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;

GROUP BY ROLLUP은 각각 그룹화 집합이라고 하는 ROLLUP 목록의 표현식 접두사에 대한 GROUP BY 결과를 반환합니다. ROLLUP 목록 (a, b, c)의 경우 그룹화 집합은 (a, b, c), (a, b), (a), ()입니다. 특정 그룹화 집합에 대한 GROUP BY 결과 평가 시 GROUP BY ROLLUP은 그룹화 집합에 없는 표현식에 NULL 값이 있는 것으로 취급합니다. 다음과 같은 SELECT 문은

SELECT a,    b,    SUM(c) FROM Input GROUP BY ROLLUP(a, b);

롤업 목록 (a, b)를 사용합니다. 결과에는 모든 행을 포함하는 그룹화 집합 (a, b), (a), ()에 대한 GROUP BY의 결과가 포함됩니다. 이는 다음과 동일한 행을 반환합니다.

SELECT NULL, NULL, SUM(c) FROM Input               UNION ALL
SELECT a,    NULL, SUM(c) FROM Input GROUP BY a    UNION ALL
SELECT a,    b,    SUM(c) FROM Input GROUP BY a, b;

이를 통해 ROLLUP 목록의 표현식과 해당 목록의 접두사로 정의되는 그룹화 집합에 대한 집계를 계산할 수 있습니다.

예:

WITH Sales AS (
  SELECT 123 AS sku, 1 AS day, 9.99 AS price UNION ALL
  SELECT 123, 1, 8.99 UNION ALL
  SELECT 456, 1, 4.56 UNION ALL
  SELECT 123, 2, 9.99 UNION ALL
  SELECT 789, 3, 1.00 UNION ALL
  SELECT 456, 3, 4.25 UNION ALL
  SELECT 789, 3, 0.99
)
SELECT
  day,
  SUM(price) AS total
FROM Sales
GROUP BY ROLLUP(day);

위의 쿼리는 NULL 날짜로 표시되는 전체 날짜에서 롤업된 총합과 함께 각 날짜에 대한 행을 출력합니다.

+------+-------+
| day  | total |
+------+-------+
| NULL | 39.77 |
|    1 | 23.54 |
|    2 |  9.99 |
|    3 |  6.24 |
+------+-------+

예:

WITH Sales AS (
  SELECT 123 AS sku, 1 AS day, 9.99 AS price UNION ALL
  SELECT 123, 1, 8.99 UNION ALL
  SELECT 456, 1, 4.56 UNION ALL
  SELECT 123, 2, 9.99 UNION ALL
  SELECT 789, 3, 1.00 UNION ALL
  SELECT 456, 3, 4.25 UNION ALL
  SELECT 789, 3, 0.99
)
SELECT
  sku,
  day,
  SUM(price) AS total
FROM Sales
GROUP BY ROLLUP(sku, day)
ORDER BY sku, day;

쿼리는 다음 그룹화 집합으로 그룹화되는 행을 반환합니다.

  • sku와 날짜
  • sku(날짜는 NULL)
  • 빈 그룹화 집합(날짜와 sku는 NULL)

이러한 그룹화 집합의 합계는 각 고유한 sku-날짜 조합의 총합, 전체 날짜에서 각 sku의 총합, 전체 총합에 해당합니다.

+------+------+-------+
| sku  | day  | total |
+------+------+-------+
| NULL | NULL | 39.77 |
|  123 | NULL | 28.97 |
|  123 |    1 | 18.98 |
|  123 |    2 |  9.99 |
|  456 | NULL |  8.81 |
|  456 |    1 |  4.56 |
|  456 |    3 |  4.25 |
|  789 |    3 |  1.99 |
|  789 | NULL |  1.99 |
+------+------+-------+

HAVING 절

구문

HAVING bool_expression

HAVING 절은 WHERE 절과 유사합니다. bool_expression에 대해 평가되면 TRUE를 반환하지 않는 행을 필터링합니다.

WHERE 절과 마찬가지로 bool_expression은 부울을 반환하는 표현식일 수 있으며 여러 하위 조건을 포함할 수 있습니다.

HAVING 절은 다음과 같은 점에서 WHERE 절과 다릅니다.

  • HAVING 절에는 GROUP BY 또는 퀴리에 있어야 하는 집계가 필요합니다.
  • HAVING 절은 GROUP BY 및 집계 이후, 그리고 ORDER BY 이전에 발생합니다. 즉, HAVING 절은 결과 조합에서 집계된 모든 행에 대해 한 번만 평가됩니다. 이 점이 GROUP BY 및 집계 이전에 평가되는 WHERE 절과 다릅니다.

HAVING 절은 SELECT 목록 별칭뿐만 아니라 FROM 절을 통해 사용할 수 있는 열을 참조할 수 있습니다. 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 절 자체에 있을 필요는 없지만 적어도 다음 형식 중 한 형식으로 있어야 합니다.

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 절 모두에 있는 경우 집계 함수와 이들이 참조하는 열이 같을 필요는 없습니다. 아래 예에서는 COUNT()SUM() 등 두 집계 함수가 다르며, 또한 서로 다른 열을 사용합니다.

SELECT LastName, COUNT(*)
FROM PlayerStats
GROUP BY LastName
HAVING SUM(PointsScored) > 15;

ORDER BY 절

구문

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

ORDER BY 절은 열 또는 표현식을 결과 조합의 정렬 기준으로 지정합니다. ORDER BY 절이 없으면 쿼리 결과 순서는 정의되지 않습니다. 기본 정렬 방향은 ASC이며, expression 값의 결과를 오름차순으로 정렬합니다. DESC는 결과를 내림차순으로 정렬합니다. FROM 절 또는 SELECT 목록의 열 별칭이 허용됩니다. 쿼리에 SELECT 절의 별칭이 포함되어 있으면 별칭으로 해당 FROM 절의 이름이 재정의됩니다.

여러 열을 기준으로 정렬할 수 있습니다. 아래 예에서 결과 조합은 먼저 SchoolID로, 그 다음에는 LastName으로 정렬됩니다.

SELECT LastName, PointsScored, OpponentID
FROM PlayerStats
ORDER BY SchoolID, LastName;

값 정렬 시 다음 규칙이 적용됩니다.

  • NULL: ORDER BY 절의 컨텍스트에서 NULL은 최소 가능 값입니다. 즉, NULL은 ASC 정렬에서 첫 번째로 나타나고 DESC 정렬에서 마지막으로 나타납니다.
  • 부동 소수점 데이터 유형: 정렬 및 그룹화에 대해서는 부동 소수점 의미 체계를 참조하세요.

집합 연산자와 함께 사용된 경우 ORDER BY 절은 가장 가까운 SELECT 문에만 적용되는 것이 아니라 전체 쿼리의 결과 조합에 적용됩니다. 그렇기 때문에, 괄호를 사용하여 ORDER BY 범위를 표시하는 것이 유용할 수 있습니다(필수는 아님).

괄호 없는 쿼리:

SELECT * FROM Roster
UNION ALL
SELECT * FROM TeamMascot
ORDER BY SchoolID;

괄호를 포함시켜 나타낸 동일한 쿼리:

( SELECT * FROM Roster
  UNION ALL
  SELECT * FROM TeamMascot )
ORDER BY SchoolID;

ORDER BY 절이 두 번째 SELECT 문에만 적용된 이 쿼리는 다른 쿼리입니다.

SELECT * FROM Roster
UNION ALL
( SELECT * FROM TeamMascot
  ORDER BY SchoolID );

또한 ORDER BY 절에서 정수 리터럴을 열 참조로 사용할 수 있습니다. 정수 리터럴은 SELECT 목록의 서수(예: 1부터 카운트 시작)가 됩니다.

예 - 다음 두 쿼리는 동일합니다.

SELECT SUM(PointsScored), LastName
FROM PlayerStats
ORDER BY LastName;
SELECT SUM(PointsScored), LastName
FROM PlayerStats
ORDER BY 2;

집합 연산자

구문

UNION { ALL | DISTINCT } | INTERSECT DISTINCT | EXCEPT DISTINCT

집합 연산자는 입력 쿼리 결과 두 개 이상을 단일 결과 조합으로 결합합니다. ALL 또는 DISTINCT를 지정해야 합니다. ALL을 지정하면 모든 행이 유지됩니다. DISTINCT가 지정되면 중복 행은 삭제됩니다.

지정된 R 행이 첫 번째 입력 쿼리에서 정확히 m번 나타나고 두 번째 입력 쿼리에서 n번 나타나는 경우(m > = 0, n > = 0):

  • UNION ALL의 경우 R은 결과에 정확히 m + n번 나타납니다.
  • UNION DISTINCT의 경우 DISTINCTUNION이 계산된 후 계산되므로 R은 정확히 한 번 나타납니다.
  • INTERSECT DISTINCT의 경우 DISTINCT는 위의 결과가 계산된 후에 계산됩니다.
  • EXCEPT DISTINCT의 경우 m > 0 및 n = 0이면 R 행은 출력에 한 번 나타납니다.
  • 입력 쿼리가 두 개 이상 있는 경우 위의 연산이 일반화되며 출력은 입력이 왼쪽에서 오른쪽으로 점진적으로 결합된 경우와 동일합니다.

다음 규칙이 적용됩니다.

  • UNION ALL 이외의 집합 연산의 경우 모든 열 유형이 동등 비교를 지원해야 합니다.
  • 연산자의 각 측의 입력 쿼리는 동일한 수의 열을 반환해야 합니다.
  • 연산자는 각 입력 쿼리에서 반환된 열을 각 SELECT 목록의 열 위치에 따라 쌍으로 만듭니다. 즉, 첫 번째 입력 쿼리의 첫 번째 열은 두 번째 입력 쿼리의 첫 번째 열과 연결됩니다.
  • 결과 조합은 항상 첫 번째 입력 쿼리의 열 이름을 사용합니다.
  • 결과 조합은 항상 해당 열에서 입력 유형의 상위 형식을 사용하므로, 쌍을 이룬 열 또한 동일한 데이터 유형이나 공통 상위 유형을 가져야 합니다.
  • 괄호를 사용하여 서로 다른 집합 연산을 구분해야 합니다. 이를 위해 UNION ALLUNION DISTINCT와 같은 집합 연산자는 서로 다릅니다. 문이 동일한 집합 연산만 반복하는 경우에는 괄호가 필요하지 않습니다.

예:

query1 UNION ALL (query2 UNION DISTINCT query3)
query1 UNION ALL query2 UNION ALL query3

잘못됨:

query1 UNION ALL query2 UNION DISTINCT query3
query1 UNION ALL query2 INTERSECT ALL query3; // INVALID.

UNION

UNION 연산자는 각 쿼리의 결과 조합에 있는 열을 쌍으로 만들고 이를 세로로 연결하여 두 개 이상의 입력 쿼리 결과 조합을 결합합니다.

INTERSECT

INTERSECT 연산자는 왼쪽 및 오른쪽 입력 쿼리의 결과 조합에서 발견된 행을 반환합니다. EXCEPT와 달리 입력 쿼리의 위치(INTERSECT 연산자의 왼쪽과 오른쪽)는 중요하지 않습니다.

EXCEPT

EXCEPT 연산자는 왼쪽 입력 쿼리에서 오른쪽 입력 쿼리에 없는 행을 반환합니다.

LIMIT 절과 OFFSET 절

구문

LIMIT count [ OFFSET skip_rows ]

LIMIT는 INT64 유형의 음수가 아닌 count를 지정하며 count 행 이상이 반환되지 않습니다. LIMIT 0은 0개의 행을 반환합니다. 집합 연산이 있으면 집합 연산이 평가된 후에 LIMIT가 적용됩니다.

OFFSET은 INT64 유형의 음수가 아닌 skip_rows를 지정하며 테이블에서 해당 오프셋의 행만 고려합니다.

이 절은 리터럴 또는 매개변수 값만 허용합니다.

LIMITOFFSET에서 반환된 행은 ORDER BY 뒤에 이러한 연산자가 사용되지 않으면 지정되지 않습니다.

WITH 절

WITH 절에는 이후 SELECT 문에서 참조할 때마다 실행되는 명명된 하위 쿼리가 한 개 이상 포함되어 있습니다. 모든 절 또는 하위 쿼리는 WITH 절에서 사용자가 정의한 하위 쿼리를 참조할 수 있습니다. 여기에는 UNION과 같이 집합 연산자의 양쪽에 있는 SELECT 문이 포함됩니다.

BigQuery는 WITH 절 내에서 쿼리 결과를 구체화하지 않으므로, WITH 절은 주로 가독성 면에서 유용합니다. 쿼리가 WITH 절 한 개 이상에서 나타날 경우 각 절에서 쿼리가 실행됩니다.

예:

WITH subQ1 AS (SELECT SchoolID FROM Roster),
     subQ2 AS (SELECT OpponentID FROM PlayerStats)
SELECT * FROM subQ1
UNION ALL
SELECT * FROM subQ2;

WITH 절의 또 다른 유용한 역할은 복잡한 쿼리를 WITH SELECT 문과 WITH 절로 나누는 것이며, 여기서 권장하지 않는 대안은 중첩된 테이블 하위 쿼리를 작성하는 것입니다. WITH 절에 여러 하위 쿼리가 포함된 경우 하위 쿼리 이름은 반복될 수 없습니다.

BigQuery는 테이블 하위 쿼리, 표현식 하위 쿼리 등과 같은 하위 쿼리에서 WITH 절을 지원합니다.

WITH q1 AS (my_query)
SELECT *
FROM
  (WITH q2 AS (SELECT * FROM q1) SELECT * FROM q2)

다음은 WITH 절에 대한 범위 지정 규칙입니다.

  • WITH 절에 도입된 별칭은 동일 WITH 절의 이후 하위 쿼리와 WITH 절 아래의 쿼리에서만 공개되도록 별칭의 범위가 지정됩니다.
  • 동일한 WITH 절에 도입된 별칭은 고유해야 하지만 동일한 쿼리의 여러 WITH 절에서 동일한 별칭을 사용할 수 있습니다. 로컬 별칭은 로컬 별칭이 공개되는 모든 위치에서 외부 별칭을 재정의합니다.
  • WITH 절에서 별칭이 지정된 하위 쿼리는 서로 관련될 수 없습니다. 쿼리 외부의 열은 표시되지 않습니다. 공개되는 유일한 외부 이름은 이전에 동일한 WITH 절에 도입되었던 다른 WITH 별칭입니다.

다음은 WITH 하위 쿼리에서 별칭을 사용하는 문의 예입니다.

WITH q1 AS (my_query)
SELECT *
FROM
  (WITH q2 AS (SELECT * FROM q1),  # q1 resolves to my_query
        q3 AS (SELECT * FROM q1),  # q1 resolves to my_query
        q1 AS (SELECT * FROM q1),  # q1 (in the query) resolves to my_query
        q4 AS (SELECT * FROM q1)   # q1 resolves to the WITH subquery
                                   # on the previous line.
    SELECT * FROM q1)  # q1 resolves to the third inner WITH subquery.

BigQuery는 WITH RECURSIVE를 지원하지 않습니다.

별칭

별칭은 퀴리에 있는 테이블, 열 또는 표현식에 제공되는 임시 이름입니다. SELECT 목록이나 FROM 절에서 명시적 별칭을 도입할 수 있습니다. 그렇지 않으면 BigQuery가 일부 표현식에 대해 암시적 별칭을 추론합니다. 명시적 또는 암시적 별칭이 없는 표현식은 익명이며 쿼리가 이름으로 별칭을 참조할 수 없습니다.

명시적 별칭 구문

FROM 절 또는 SELECT 목록에 명시적 별칭을 도입할 수 있습니다.

FROM 절에서 [AS] alias를 사용하여 테이블, 배열, 하위 쿼리, UNNEST 절을 포함한 모든 항목에 명시적 별칭을 도입할 수 있습니다. 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;

명시적 별칭 공개

쿼리에 명시적 별칭을 도입하면 쿼리에서 해당 별칭을 참조할 수 있는 다른 위치가 제한됩니다. 별칭 공개에 대한 이러한 제한은 BigQuery의 이름 범위 지정 규칙에 따른 것입니다.

FROM 절 별칭

BigQuery는 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;

FROM 절에 명시적 별칭이 있는 경우, 쿼리의 나머지 부분에 대한 암시적 별칭 대신 이 명시적 별칭을 사용해야 합니다(암시적 별칭 참조). 테이블 별칭은 쿼리 처리 중 동일한 테이블을 여러 번 검사하는 자체 조인과 같은 경우에 모호성을 없애기 위해 또는 간결성을 위해 사용될 수 있습니다.

예:

SELECT * FROM Singers as s, Songs as s2
ORDER BY s.LastName

잘못됨 — ORDER BY는 테이블 별칭을 사용하지 않습니다.

SELECT * FROM Singers as s, Songs as s2
ORDER BY Singers.LastName;  // INVALID.

SELECT 목록 별칭

SELECT 목록의 별칭은 다음 절에만 표시됩니다.

  • GROUP BY
  • ORDER BY
  • HAVING

예:

SELECT LastName AS last, SingerID
FROM Singers
ORDER BY last;

GROUP BY, ORDER BY, HAVING 절의 명시적 별칭

GROUP BY, ORDER BY, HAVING 등 세 가지 절은 다음 값만 참조할 수 있습니다.

  • FROM 절의 테이블과 해당 열
  • SELECT 목록의 별칭

또한 GROUP BYORDER BY는 세 번째 그룹을 참조할 수 있습니다.

  • SELECT 목록의 항목을 참조하는 정수 리터럴. 정수 1SELECT 목록의 첫 번째 항목을 참조하고 2는 두 번째 항목을 참조합니다.

예:

SELECT SingerID AS sid, COUNT(Songid) AS s2id
FROM Songs
GROUP BY 1
ORDER BY 2 DESC;

위 쿼리는 다음과 같습니다.

SELECT SingerID AS sid, COUNT(Songid) AS s2id
FROM Songs
GROUP BY sid
ORDER BY s2id DESC;

모호한 별칭

이름이 모호한 경우 BigQuery에서 오류가 발생합니다. 이는 한 개 이상의 고유 객체로 해석될 수 있다는 의미입니다.

예:

SingersSongs 모두에 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 절의 LastNameSingers의 원래 열 LastName을 참조하거나 값이 UPPER(LastName)인 별칭 AS LastName을 참조할 수 있으므로, 오류가 발생합니다.

모호성에 대한 동일한 규칙이 경로 표현식에 적용됩니다. table에 열 xy가 있고 열 z가 STRUCT 유형이며 필드 v, w, x를 가지고 있는 다음과 같은 쿼리를 가정해 보겠습니다.

예:

SELECT x, z AS T
FROM table T
GROUP BY T.x;

별칭 T는 모호하며 GROUP BY 절의 T.xtable.x 또는 table.z.x를 참조할 수 있으므로 오류가 발생합니다.

열 이름이면서 SELECT 목록 별칭인 경우, 이름이 동일한 기본 객체로 확인되면 이름은 GROUP BY, ORDER BY 또는 HAVING에서 모호하지 않습니다.

예:

SELECT LastName, BirthYear AS BirthYear
FROM Singers
GROUP BY BirthYear;

별칭 BirthYear는 동일한 기본 열인 Singers.BirthYear로 확인되므로 모호하지 않습니다.

암시적 별칭

SELECT 목록에 명시적 별칭이 없는 표현식이 있으면 BigQuery는 다음 규칙에 따라 암시적 별칭을 할당합니다. SELECT 목록에는 동일한 별칭을 가진 열이 여러 개 있을 수 있습니다.

  • 식별자의 경우 별칭은 식별자입니다. 예를 들어, SELECT abcAS abc를 암시합니다.
  • 경로 표현식의 경우 별칭은 경로의 마지막 식별자입니다. 예를 들어, SELECT abc.def.ghiAS ghi를 암시합니다.
  • 'dot' 구성원 필드 액세스 연산자를 사용하는 필드 액세스의 경우 별칭은 필드 이름입니다. 예를 들어, SELECT (struct_function()).fnameAS fname을 암시합니다.

다른 모든 경우에는 암시적 별칭이 없으므로, 열은 익명이며 이름으로 참조될 수 없습니다. 해당 열의 데이터는 계속 반환되며 표시된 쿼리 결과에 해당 열에 대해 생성된 라벨이 있을 수 있지만 별칭처럼 사용될 수 없습니다.

FROM 절에서 from_item은 별칭을 가질 필요가 없습니다. 다음 규칙이 적용됩니다.

  • 명시적 별칭이 없는 표현식이 있는 경우, BigQuery는 다음과 같은 경우에 암시적 별칭을 할당합니다.
    • 식별자의 경우 별칭은 식별자입니다. 예를 들어, FROM abcAS abc를 암시합니다.
    • 경로 표현식의 경우 별칭은 경로의 마지막 식별자입니다. 예를 들어, FROM abc.def.ghiAS ghi를 암시합니다.
    • WITH OFFSET을 사용하여 생성된 열에는 암시적 별칭 offset이 있습니다.
  • 테이블 하위 쿼리에는 암시적 별칭이 없습니다.
  • FROM UNNEST(x)에는 암시적 별칭이 없습니다.

부록 A: 샘플 데이터가 있는 예

샘플 테이블

다음 세 개의 테이블에는 운동 선수, 학교, 시즌 중에 이들이 획득한 점수에 대한 샘플 데이터가 있습니다. 이 테이블은 여러 가지 쿼리 절의 동작을 설명하는 데 사용됩니다.

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 Mascot
50 Jaguars
51 Knights
52 Lakers
53 Mustangs

TeamMascot 테이블에는 고유 학교 ID(SchoolID)와 해당 학교의 마스코트(Mascot) 목록이 포함되어 있습니다.

JOIN 유형

1) [INNER] JOIN

예:

SELECT * FROM Roster JOIN TeamMascot
ON Roster.SchoolID = TeamMascot.SchoolID;

결과:

LastName Roster.SchoolId TeamMascot.SchoolId Mascot
Adams 50 50 Jaguars
Buchanan 52 52 Lakers
Coolidge 52 52 Lakers
Davis 51 51 Knights

2) CROSS JOIN

예:

SELECT * FROM Roster CROSS JOIN TeamMascot
ON Roster.SchoolID = TeamMascot.SchoolID;

결과:

LastName Roster.SchoolId TeamMascot.SchoolId Mascot
Adams 50 50 Jaguars
Adams 50 51 Knights
Adams 50 52 Lakers
Adams 50 53 Mustangs
Buchanan 52 50 Jaguars
Buchanan 52 51 Knights
Buchanan 52 52 Lakers
Buchanan 52 53 Mustangs
Coolidge 52 50 Jaguars
Coolidge 52 51 Knights
Coolidge 52 52 Lakers
Coolidge 52 53 Mustangs
Davis 51 50 Jaguars
Davis 51 51 Knights
Davis 51 52 Lakers
Davis 51 53 Mustangs
Eisenhower 77 50 Jaguars
Eisenhower 77 51 Knights
Eisenhower 77 52 Lakers
Eisenhower 77 53 Mustangs

3) FULL [OUTER] JOIN

예:

SELECT * FROM Roster FULL JOIN TeamMascot
ON Roster.SchoolID = TeamMascot.SchoolID;
LastName Roster.SchoolId TeamMascot.SchoolId Mascot
Adams 50 50 Jaguars
Buchanan 52 52 Lakers
Coolidge 52 52 Lakers
Davis 51 51 Knights
Eisenhower 77 NULL NULL
NULL NULL 53 Mustangs

4) LEFT [OUTER] JOIN

예:

SELECT * FROM Roster LEFT JOIN TeamMascot
ON Roster.SchoolID = TeamMascot.SchoolID;

결과:

LastName Roster.SchoolId TeamMascot.SchoolId Mascot
Adams 50 50 Jaguars
Buchanan 52 52 Lakers
Coolidge 52 52 Lakers
Davis 51 51 Knights
Eisenhower 77 NULL NULL

5) RIGHT [OUTER] JOIN

예:

SELECT * FROM Roster RIGHT JOIN TeamMascot
ON Roster.SchoolID = TeamMascot.SchoolID;

결과:

LastName Roster.SchoolId TeamMascot.SchoolId Mascot
Adams 50 50 Jaguars
Davis 51 51 Knights
Coolidge 52 52 Lakers
Buchanan 52 52 Lakers
NULL NULL 53 Mustangs

GROUP BY 절

예:

SELECT LastName, SUM(PointsScored)
FROM PlayerStats
GROUP BY LastName;
LastName SUM
Adams 7
Buchanan 13
Coolidge 1

집합 연산자

UNION

UNION 연산자는 각 SELECT 문의 결과 조합에 있는 열을 쌍으로 만들고 이를 세로로 연결하여 SELECT 문 두 개 이상의 결과 조합을 결합합니다.

예:

SELECT Mascot AS X, SchoolID AS Y
FROM TeamMascot
UNION ALL
SELECT LastName, PointsScored
FROM PlayerStats;

결과:

X Y
Mustangs 50
Knights 51
Lakers 52
Mustangs 53
Adams 3
Buchanan 0
Coolidge 1
Adams 4
Buchanan 13

INTERSECT

이 쿼리는 Roster와 PlayerStats 모두에 있는 성을 반환합니다.

SELECT LastName
FROM Roster
INTERSECT DISTINCT
SELECT LastName
FROM PlayerStats;

결과:

LastName
Adams
Coolidge
Buchanan

EXCEPT

아래 쿼리는 PlayerStats에는 없고 Roster에만 있는 성을 반환합니다.

SELECT LastName
FROM Roster
EXCEPT DISTINCT
SELECT LastName
FROM PlayerStats;

결과:

LastName
Eisenhower
Davis

SELECT 문 순서를 반대로 하면 Roster에는 없고 PlayerStats에만 있는 성이 반환됩니다.

SELECT LastName
FROM PlayerStats
EXCEPT DISTINCT
SELECT LastName
FROM Roster;

결과:

(empty)
이 페이지가 도움이 되었나요? 평가를 부탁드립니다.

다음에 대한 의견 보내기...

도움이 필요하시나요? 지원 페이지를 방문하세요.