카테고리:

쿼리 구문

GROUP BY GROUPING SETS

GROUP BY GROUPING SETS는 단일 문에서 여러 group-by 절을 계산하는 GROUP BY 절의 강력한 확장입니다. 그룹 세트는 차원 열 세트입니다.

GROUP BY GROUPING SETS는 동일한 결과 세트에서 두 개 이상의 GROUP BY 작업의 UNION 과 동등합니다.

  • GROUP BY GROUPING SETS(a) 는 단일 그룹화 세트 연산 GROUP BY a 와 동등합니다.

  • GROUP BY GROUPING SETS(a,b)GROUP BY a UNION ALL GROUP BY b 와 동등합니다.

구문

SELECT ...
FROM ...
[ ... ]
GROUP BY GROUPING SETS ( groupSet [ , groupSet [ , ... ] ] )
[ ... ]
Copy

여기서:

groupSet ::= { <column_alias> | <position> | <expr> }
Copy
column_alias

쿼리 블록의 SELECT 목록에 나타나는 열 별칭입니다.

position

SELECT 목록에서 식의 위치입니다.

expr

현재 범위의 테이블에 대한 모든 식입니다.

사용법 노트

  • Snowflake는 동일한 쿼리 블록에서 최대 128개의 그룹화 세트를 허용합니다.

  • 출력에는 일반적으로 일부 NULL 값이 포함됩니다. GROUP BY ROLLUP 은 각각 다른 기준으로 그룹화된 둘 이상의 결과 세트의 결과를 병합하기 때문에, 한 결과 세트에 단일 값이 있는 일부 열은 다른 결과 세트에 많은 해당 값을 가질 수 있습니다. 예를 들어, 부서별로 그룹화된 직원 세트를 직위별로 그룹화한 세트와 함께 UNION 을 수행하는 경우, 가장 높은 직위를 가진 세트의 구성원이 반드시 같은 부서에 있는 것은 아니므로 부서_이름의 값이 NULL로 설정됩니다. 이러한 이유로 다음 예시에는 NULL이 포함되어 있습니다.

이 예에서는 재해 지원을 위해 훈련된 간호사에 대한 정보 테이블을 사용합니다. 이 모든 간호사는 간호사 면허(예: RN은 《등록 간호사》 면허가 있음)와 수색 및 구조, 무선 통신 등의 재해 관련 전문 분야의 추가 면허를 가지고 있습니다. 이 예에서는 두 가지 카테고리의 면허만 단순화하여 사용합니다.

  • 간호: RN(등록 간호사) 및 LVN(면허가 있는 직업 간호사).

  • 아마추어(《햄》) 무선: 햄 무선 면허에는 《Technician》, 《General》, 《Amateur Extra》가 포함됩니다.

다음은 테이블을 만들고 로딩하는 명령입니다.

CREATE or replace TABLE nurses (
  ID INTEGER,
  full_name VARCHAR,
  medical_license VARCHAR,   -- LVN, RN, etc.
  radio_license VARCHAR      -- Technician, General, Amateur Extra
  )
  ;

INSERT INTO nurses
    (ID, full_name, medical_license, radio_license)
  VALUES
    (201, 'Thomas Leonard Vicente', 'LVN', 'Technician'),
    (202, 'Tamara Lolita VanZant', 'LVN', 'Technician'),
    (341, 'Georgeann Linda Vente', 'LVN', 'General'),
    (471, 'Andrea Renee Nouveau', 'RN', 'Amateur Extra')
    ;
Copy

이 쿼리는 GROUP BY GROUPING SETS 를 사용합니다.

SELECT COUNT(*), medical_license, radio_license
  FROM nurses
  GROUP BY GROUPING SETS (medical_license, radio_license);
Copy

출력:

처음 두 행은 RN 및 LVN(간호 면허의 두 가지 유형) 수를 보여줍니다. 이 두 행에 대한 RADIO_LICENSE 열의 NULL 값은 의도적입니다. 쿼리는 해당 무선 면허와 관계없이 모든 LVN(및 모든 RN을 함께)을 그룹화하므로, 결과는 해당 행에 그룹화된 모든 LVN 또는 RN에 반드시 적용되는 각 행의 RADIO_LICENSE 열에 하나의 값을 표시할 수 없습니다.

다음 세 행은 각 유형의 햄 무선 면허(《Technician》, 《General》, 《Amateur Extra》)를 가진 간호사의 수를 보여줍니다. 이러한 세 행 각각의 MEDICAL_LICENSE에 대한 NULL 값은 의도적입니다. 단일 의료 면허가 각 행의 모든 구성원에게 반드시 적용되는 것은 아니기 때문입니다.

+----------+-----------------+---------------+
| COUNT(*) | MEDICAL_LICENSE | RADIO_LICENSE |
|----------+-----------------+---------------|
|        3 | LVN             | NULL          |
|        1 | RN              | NULL          |
|        2 | NULL            | Technician    |
|        1 | NULL            | General       |
|        1 | NULL            | Amateur Extra |
+----------+-----------------+---------------+

다음 예에서는 일부 열에 NULL 값이 포함된 경우 어떤 일이 발생하는지 보여줍니다. 아직 햄 무선 면허가 없는 새 간호사 3명을 추가하여 시작합니다.

INSERT INTO nurses
    (ID, full_name, medical_license, radio_license)
  VALUES
    (101, 'Lily Vine', 'LVN', NULL),
    (102, 'Larry Vancouver', 'LVN', NULL),
    (172, 'Rhonda Nova', 'RN', NULL)
    ;
Copy

그런 다음 이전과 동일한 쿼리를 실행합니다.

SELECT COUNT(*), medical_license, radio_license
  FROM nurses
  GROUP BY GROUPING SETS (medical_license, radio_license);
Copy

출력:

처음 5줄은 이전 쿼리와 동일합니다.

마지막 줄의 경우, 처음에는 혼란스러울 수 있습니다. 두 열에 모두 NULL이 있는 줄이 왜 존재하는지, 그리고 모든 값이 NULL이면 COUNT(*)가 왜 3인지에 관해 의문이 발생하기 때문입니다.

대답은, 해당 행의 RADIO_LICENSE 열에서 NULL이 발생하는 이유는 세 간호사에게 무선 면허가 없기 때문이라는 것입니다. (《SELECT DISTINCT RADIO_LICENSE FROM 간호사》는 이제 《Technician》, 《General》, 《Amateur Extra》, 《NULL》이라는 4가지 고유한 값을 반환합니다.)

MEDICAL_LICENSES 열의 NULL은 이전 쿼리 결과에서 NULL 값이 발생한 것과 같은 이유로 발생합니다. 즉, 이 행에서 계산된 간호사는 다른 MEDICAL_LICENSES를 가지므로 하나의 값(《RN》 또는 《LVN》)이 이 행에 계산된 모든 간호사에게 반드시 적용되는 것은 아닙니다.

+----------+-----------------+---------------+
| COUNT(*) | MEDICAL_LICENSE | RADIO_LICENSE |
|----------+-----------------+---------------|
|        5 | LVN             | NULL          |
|        2 | RN              | NULL          |
|        2 | NULL            | Technician    |
|        1 | NULL            | General       |
|        1 | NULL            | Amateur Extra |
|        3 | NULL            | NULL          |
+----------+-----------------+---------------+

원하는 경우, 이 출력을 GROUPING SETS 절이 없는 GROUP BY 의 출력과 비교할 수 있습니다.

SELECT COUNT(*), medical_license, radio_license
  FROM nurses
  GROUP BY medical_license, radio_license;
Copy

출력:

+----------+-----------------+---------------+
| COUNT(*) | MEDICAL_LICENSE | RADIO_LICENSE |
|----------+-----------------+---------------|
|        2 | LVN             | Technician    |
|        1 | LVN             | General       |
|        1 | RN              | Amateur Extra |
|        2 | LVN             | NULL          |
|        1 | RN              | NULL          |
+----------+-----------------+---------------+