GROUP BY를 사용하여 데이터 요약

완료됨

집계 함수는 분석에 유용하지만 요약하기 전에 데이터를 하위 집합으로 정렬하는 것이 좋습니다. 이 섹션에서는 GROUP BY 절을 사용하여 이 작업을 수행하는 방법을 알아봅니다.

GROUP BY 절 사용

학습한 대로 SELECT 문이 처리되면 FROM 절 및 WHERE 절이 평가된 후 가상 테이블이 만들어집니다. 이제 가상 테이블의 내용을 추가 처리에 사용할 수 있습니다. GROUP BY 절을 사용하여 이 가상 테이블의 내용을 행 그룹으로 세분화할 수 있습니다.

행을 그룹화하려면 GROUP BY 절에서 하나 이상의 요소를 지정합니다.

GROUP BY <value1> [, <value2>, …]

GROUP BY는 절에 지정된 요소에 의해 결정된 대로 그룹을 만들고 각 그룹에 행을 배치합니다.

예를 들어 다음 쿼리는 Sales.SalesOrderHeader 테이블에서 CustomerID당 한 행씩 그룹화된 행 집합을 생성합니다. GROUP BY 프로세스를 살펴보는 또 다른 방법은 CustomerID 에 대해 동일한 값을 가진 모든 행이 함께 그룹화되고 단일 결과 행에 반환된다는 것입니다.

SELECT CustomerID
FROM Sales.SalesOrderHeader
GROUP BY CustomerID;

위의 쿼리는 다음 쿼리와 동일합니다.

SELECT DISTINCT CustomerID
FROM Sales.SalesOrderHeader

GROUP BY 절이 처리되고 각 행이 그룹과 연결되면 쿼리의 이후 단계에서는 SELECT 목록에 있지만 GROUP BY 목록에 표시되지 않는 원본 행의 모든 요소를 집계해야 합니다. 이 요구 사항은 SELECT 및 HAVING 절을 작성하는 방법에 영향을 줍니다.

그렇다면 GROUP BY 또는 DISTINCT를 사용하여 쿼리를 작성하는 것의 차이점은 무엇인가요? CustomerID에 대한 고유 값만 알고 싶은 경우 차이가 없습니다. 그러나 GROUP BY를 사용하면 SELECT 목록에 다른 요소를 추가한 다음 각 그룹에 대해 집계할 수 있습니다.

가장 간단한 집계 함수는 COUNT(*)입니다. 다음 쿼리는 CustomerID 의 원래 830개 원본 행을 가져와 CustomerID 값에 따라 89개의 그룹으로 그룹화합니다. 각 고유한 CustomerID 값은 GROUP BY 쿼리에서 하나의 출력 행을 생성합니다.

SELECT CustomerID, COUNT(*) AS OrderCount
FROM Sales.SalesOrderHeader
GROUP BY CustomerID;

CustomerID 값에 대해 쿼리는 행을 집계하고 계산하므로 SalesOrderHeader 테이블의 행 수가 각 고객에게 속하는 수를 보여 줍니다.

고객ID

OrderCount

1234

3

1005

1

GROUP BY는 결과의 순서를 보장하지 않습니다. 종종 쿼리 프로세서에서 그룹화 작업을 수행하는 방식의 결과로 결과가 그룹 값의 순서대로 반환됩니다. 그러나 이 동작에 의존해서는 안 됩니다. 결과를 정렬해야 하는 경우 ORDER 절을 명시적으로 포함해야 합니다.

SELECT CustomerID, COUNT(*) AS OrderCount
FROM Sales.SalesOrderHeader
GROUP BY CustomerID
ORDER BY CustomerID;

이번에는 결과가 지정된 순서로 반환됩니다.

고객ID

OrderCount

1005

1

1234

3

SELECT 문의 절은 다음 순서로 적용됩니다.

  1. 발신자
  2. 어디
  3. GROUP BY (그룹화를 위한 SQL 구문)
  4. 가지고 있는
  5. 선택
  6. 정렬 기준 (ORDER BY)

열 별칭은 GROUP BY 절 뒤에 있지만 ORDER BY 절 앞에 발생하는 SELECT 절에 할당됩니다. ORDER BY 절에서는 열 별칭을 참조할 수 있지만 GROUP BY 절에서는 참조할 수 없습니다. 다음 쿼리에서 잘못된 열 이름 오류가 발생합니다.

SELECT CustomerID AS Customer,
       COUNT(*) AS OrderCount
FROM Sales.SalesOrderHeader
GROUP BY Customer
ORDER BY Customer;

그러나 다음 쿼리는 고객 ID별로 결과를 그룹화하고 정렬하는 데 성공합니다.

SELECT CustomerID AS Customer,
       COUNT(*) AS OrderCount
FROM Sales.SalesOrderHeader
GROUP BY CustomerID
ORDER BY Customer;

GROUP BY 오류 문제 해결

SELECT 문에서 GROUP BY를 사용하는 데 익숙해지는 일반적인 장애물은 다음 유형의 오류 메시지가 발생하는 이유를 이해하는 것입니다.

Msg 8120, 수준 16, 상태 1, 줄 2 열 <column_name> 집계 함수 또는 GROUP BY 절에 포함되지 않으므로 선택 목록에서 유효하지 않습니다.

예를 들어 SELECT 목록의 각 열은 GROUP BY 절의 열이거나 각 그룹에서 작동하는 집계 함수이므로 다음 쿼리가 허용됩니다.

SELECT CustomerID, COUNT(*) AS OrderCount
FROM Sales.SalesOrderHeader
GROUP BY CustomerID;

PurchaseOrderNumber가 GROUP BY의 일부가 아니며 집계 함수와 함께 사용되지 않으므로 다음 쿼리는 오류를 반환합니다.

SELECT CustomerID, PurchaseOrderNumber, COUNT(*) AS OrderCount
FROM Sales.SalesOrderHeader
GROUP BY CustomerID;

이 쿼리는 오류를 반환합니다.

Msg 8120, Level 16, State 1, Line 1
Column 'Sales.SalesOrderHeader.PurchaseOrderNumber' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

여기에 대해 생각하는 또 다른 방법이 있습니다. 이 쿼리는 각 CustomerID 값에 대해 하나의 행을 반환합니다. 그러나 동일한 CustomerID 의 행에 다른 PurchaseOrderNumber 값이 있을 수 있으므로 어떤 값이 반환되어야 하나요?

고객 ID 및 구매 주문별 주문을 확인하려면 다음과 같이 GROUP BY 절에 PurchaseOrderNumber 열을 추가할 수 있습니다.

SELECT CustomerID, PurchaseOrderNumber, COUNT(*) AS OrderCount
FROM Sales.SalesOrderHeader
GROUP BY CustomerID, PurchaseOrderNumber;

이 쿼리는 해당 조합에 대한 주문 수와 함께 각 고객 및 각 구매 주문 조합에 대해 하나의 행을 반환합니다.