hyperskill - GROUP BY statement 원문
일찍이 우리는 집계 함수가 간단한 분석적 문제를 푸는 데 유용 할 수 있는지에 대해 배웠습니다.
이제 당신이 전체 테이블, 혹은 하나의 세부 카테고리에 대한 집계 값을 계산하지 않고,
별도의 많은 카테고리들을 계산하고 싶다고 상상 해 봅시다.
예를 들어, stocks
테이블에 가격에 대한 기록 데이터가 있습니다.
stock_name | price | datetime |
---|---|---|
WTI | 89.8 | 2020-05-17 11:00 |
FB | 26.3 | 2020-04-11 10:23 |
WTI | 18.9 | 2019-01-18 23:02 |
WTI | 20.9 | 2019-01-18 23:02 |
FB | 15.6 | NULL |
DJI | 52.7 | 2004-05-28 21:09 |
FB | 63.7 | 1998-03-31 04:18 |
밑의 쿼리는 가능 한 예제지만, 실행하기에 꽤 불편한 쿼리입니다 :
SELECT MAX(price)
FROM stocks
WHERE stock_name = 'WTI';
만약, 우리가 테이블 형태로 모든 주식에 대한 알맞는 결과들을 얻고 싶다면, 그리고 더 나아가 계산에 사용하고 싶다면?
이 워크로드를 간단히 하기 위해서, GROUP BY 문법에 SQL에 존재했습니다.
이 주제에서는, 이것이 어떻게 작동하는지에 대한 관점을 얻게 됩니다.
General form - 일반적인 형태
여기 우리가 어떻게 주어진 문제에 대해 GROUP BY
를 사용할 수 있는지가 존재합니다.
SELECT
stock_name,
MAX(price) AS maximum
FROM
stocks
GROUP BY
stock_name;
결과물은 이렇게 생겼습니다 :
stock_name | maximum |
---|---|
WTI | 89.8 |
FB | 63.7 |
DJI | 52.7 |
이 쿼리에서 무엇이 특별할까요?
GROUP BY 절에서, 우리는 테이블의 컬럼 이름을 지정했습니다.
이 컬럼의 모든 고유 값은 SELECT 절에서 활용 가능한 모든 집계 함수의 결과를 가지게 됩니다.
해석
예제에서 주어진 테이블 stocks는 중복되는 stock_name이 존재합니다.GROUP BY
로 지정된 컬럼은, 중복되는 값을 고유의 값으로 만듭니다.
중복 값을 제외하고, WTI, FB, DJI 고유 값이 나오게 되는데,
각각의 고유 값에 대해MIN
,MAX
,AVG
등등과 같은 집계 함수의 결과값을 갖고 있는다는 의미입니다.
고유 값에 알맞는 줄들의 값은 입력값처럼 가져갑니다.
현재 테이블에 표현되지 않는 계산 된 값에 의한 것으로 그룹을 만드는 것도 가능합니다.
예를 들어, 우리는 length of stock_name (주식 이름의 길이)에 기반한 그룹을 소개 할 수 있습니다.
바로 GROUP BY LENGTH(stock_name)
을 이용해서 말입니다.
어떤 것도 우리에게 하나의 집계 함수만을 사용하게 금지하지 않습니다.
반환 값들은 완벽하게 각각의 다른 것들에게서 독립되어 있습니다 :
SELECT
stock_name,
MIN(datetime) AS moment,
MAX(price) AS maximum
FROM
stocks
GROUP BY
stock_name;
stock_name | moment | maximum |
---|---|---|
WTI | 2019-01-18 23:02 | 89.8 |
FB | 1998-03-31 04:18 | 63.7 |
DJI | 2004-05-28 21:09 | 52.7 |
만약, GROUP BY
절에 여러 개의 열이 있다면,
해당 컬럼들로부터 각각의 고유한 값들의 결합이 별개로 집계됩니다.
SELECT
stock_name,
datetime,
MAX(price)
FROM
stocks
GROUP BY
stock_name,
datetime;
stock_name | datetime | price |
---|---|---|
WTI | 2020-05-17 11:00 | 89.8 |
FB | 2020-04-11 10:23 | 26.3 |
WTI | 2019-01-18 23:02 | 20.9 |
FB | NULL | 15.6 |
DJI | 2004-05-28 21:09 | 52.7 |
FB | 1998-03-31 04:18 | 63.7 |
원문을 이해하기 위한 문단
위의 테이블은 처음 주어진 테이블과 단 하나가 다릅니다..
어떠한 이유로 이러한 테이블이 나오는지 이해해야 GROUP BY
에 대해 더 이해가 갈 겁니다.
먼저, stock_name, datetime의 고유한 값들을 구해야 합니다.
stock_name
: WTI, FB, DJIdatetime
:2020-05-17 11:00
,2020-04-11 10:23
, 외 3개 (위 테이블 참조)
GROUP BY
절 내부에 1 개 이상의 컬럼 이름이 사용되었으므로, 해당 컬럼의 고유 값들의 모든 조합을 고려합니다.
그런데, datetime 컬럼 내부의 하나 빼고 전부 각기 다릅니다. 그러므로 6개의 고유 날짜 키가 나옵니다.
단 하나, 중첩되는 조합은 WTI
와 2019-01-18 23:02
입니다.
밑의 그래프로 위 예제로 발생하는 GROUP BY
의 흐름을 살펴보겠습니다.
flowchart LR
time1("2020-05-17 11:00")
time2("2020-04-11 10:23")
time3("2019-01-18 23:02")
time4("NULL")
time5("2004-05-28 21:09")
time6("1998-03-31 04:18")
time1 --> WTI1("WTI") --> max1["89.8"]
time2 --> FB1("FB") --> max2["26.3"]
time3 --> WTI2("WTI") --> max3["20.9"] --> select("max선택")
time3 --> WTI("<s>WTI</s>") --> exam("<s>18.9</s>") --> select1("<s>max 아님</s>")
time4 --> FB2("FB") --> max4["20.9"]
time5 --> DJI1("DJI") --> max5["52.7"]
time6 --> FB3("FB") --> max6["63.7"]
위의 그래프를 보다시피, 날짜에 한정해 하나의 값만 중복되는 것을 볼 수 있습니다.
예제에서는 MAX(price)
aggerate(집계) 함수를 사용했으므로,
해당 중복 결과 중 price 가 가장 높은 것을 선택합니다.
위의 과정을 통해 중복 결합이 사라진 테이블이 결과로 나오게 됩니다.
설명하기 이전의 내용과 이어서 - ..
여기 NULL 값이 별도의 카테고리로 형태를 가진 것을 볼 수 있습니다.
이는 NULL 이 고유의 값으로 고려되기 때문입니다.
- WTI, 2019-01-18 23:02, 20.9
- WTI, 2019-01-18 23:02, 18.9
두 조합 중 가장 큰 가격을 가진 조합으로 합쳐집니다.
결과론 적인 측면에서, 어떠한 집계 함수를 사용하지 않은 상태의 그룹 쿼리와 밑의 쿼리는 동일합니다 :
SELECT DISTINCT
stock_name,
datetime
FROM
stocks;
만약 컬럼이 GROUP BY
절에 있지 않으며, 적어도 하나 이상의 집계 함수가 SELECT에 사용되고 있다면,
이 컬럼은 집계 함수에 래핑(괄호)되지 않고 SELECT의 일부분으로 사용 될 수 없습니다.
Having keyword - HAVING 키워드
GROUP BY
문법은 때로 WHERE
문법으로 줄들을 거르고, ORDER BY
로 정렬하기도 합니다.
그룹화 문제들에 대해 특히 도움이 되는 다른 구문이 있습니다. - HAVING
WHERE
이 특정한 셀들이 가지는 값의 조건을 받아들인다면,
HAVING
은 같지만 다른데, 이미 집계 함수로 계산된 값들에 대해 작동하기 때문입니다.
예를 들어, 한 번 stock-datetime 의 짝의 최고 가격이 50을 넘는 경우만 선택해 보겠습니다.
SELECT
stock_name,
datetime,
MAX(price) as maximum
FROM
stocks
GROUP BY
stock_name,
datetime
HAVING
MAX(price) > 50;
stock_name | datetime | maximum |
---|---|---|
WTI | 2020-05-17 11:00 | 89.8 |
DJI | 2004-05-28 21:09 | 52.7 |
FB | 1998-03-31 04:18 | 63.7 |
여기서 나올 합당한 질문은 "왜 필터링에 WHERE 을 활용할 수 없는가?" 일 겁니다.
이에 대한 이유는 구문들의 계산 순서에 있습니다 :
- FROM
- WHERE
- GROUP BY
- HAVING
- SELECT
- ORDER BY
HAVING
에 당신이 넣은 모든 조건들은 집계 합수들에 관련이 있습니다.
게다가, 다른 특별한 제약도 없습니다.
Conclusion - 결론
요약하면서, 그룹화를 위한 쿼리의 템플릿은 이를 따릅니다 :
SELECT column_name [, list_of_other_columns]
, aggregation [, list_of_aggregations]
FROM table_name
[WHERE list_of_conditions]
GROUP BY column_name [, list_of_other_conditions]
[HAVING list_of_affregate_conditions]
[ORDER BY list_of_columns/aliases];
'Hyperskill - 컴퓨터 CS 및 영어 독해 > Introducing to SQL' 카테고리의 다른 글
Consistency constraints - 일관성 제약 조건 (0) | 2024.04.30 |
---|---|
Subqueries - 서브쿼리 (0) | 2024.04.29 |
Aggregate functions - 집계 함수들 (0) | 2024.04.27 |
Inserting selected rows - 선택된 줄 삽입하기 (0) | 2024.04.26 |
Updating selected rows - 선택된 줄들 업데이트하기 (1) | 2024.04.25 |