SELECT COUNT(*) FROM test_table;
-- COUNT : 인자로 전달된 컬럼의 개수를 새거나, 행의 개수를 셀수 있다.
-- COUNT(*) 처럼 쓴다면 그냥 행의 개수를 구하게 되고, COUNT(name) 처럼 쓴다면 name의 개수를 구하게 된다.
-- 만약 COUNT(name) 에서 name이 NULL인 행이 있다면 제외된다.
-- 이런 특성으로 특정 컬럼이 null 인 값은 집계에서 제외하고 싶다면 해당 컬럼을 COUNT의 인자로 넘기면 된다.

SELECT SUM(price * quantity) FROM test_table;
SELECT AVG(age) FROM test_table;
-- SUM : 인자로 넣은 값의 합계를 구할 수 있다.
-- 위 쿼리에서는 price * quantity 결과를 각 행별로 계산하고, 계산 결과를 합산한다.
-- AVG : 인자로 넣은 컬럼의 평균을 계산한다. 위에서는 age의 평균을 계산한다.
-- 두 함수 모두 NULL 값은 제외한다. 0으로 취급하는 것도 아니고 그냥 제외한다.

SELECT MIN(age), MAX(age) FROM test_table;
-- 각각 최솟값, 최댓값 을 찾는다.
-- 이 함수들도 NULL은 제외하고 찾게된다.

SELECT COUNT(DISTINCT age) FROM test_table;
-- 이렇게 집계 함수안에 DISTINCT 를 넣으면 집계할 컬럼의 중복을 제거하고 개수를 셀수 있다.
SELECT COUNT(*) FROM test_table GROUP BY age;
-- 이렇게 age 기준으로 묶어서 각 나이별로 몇명이 있는 지 조회할 수 있다.
-- 이 경우 NULL도 하나의 그룹으로 묶여서 그룹으로 묶은 컬럼에 NULL이 몇개나 있는지도 셀수 있다.

SELECT SUM(price) as total_price FROM test_table GROUP BY category ORDER BY total_price;
-- 이런식으로 각 카테고리별로 총 가격도 계산할 수 있다.
-- ORDER BY 를 통해 각 그룹별로 구한 총 가격을 기준으로 정렬할 수 있다.

SELECT name, SUM(price) FROM test_table GROUP BY name, category;
-- 이렇게 여러 컬럼을 기준으로 그룹핑 할수도 있다.
-- name으로 한번 그룹핑하고, 그 안에서 category별로 그룹핑 한다.
-- 예를 들어
-- (lucy, book), (lucy, phone), (jam, book) 으로 각 행이 존재한다면
-- 단순히 name으로만 묶으면 (lucy), (jam) 정도로만 묶이겠지만
-- name, category로 묶는다면 (lucy, book), (lucy, phone), (jam, book) 처럼
-- 더 자세하고 구체적으로 그룹핑 할 수 있다.
SELECT COUNT(age) FROM test_table GROUP BY age HAVING COUNT(age) > 10;
-- 이 쿼리는 각 나이별로 데이터 개수를 구하지만, 각 데이터 개수가 10개보다 큰 데이터만 조회한다.
-- 이렇게 HAVING 을 사용하면 각 그룹별로 조건을 비교해 최종으로 가져올 그룹을 필터링 할 수 있다.
-- HAVING 절에는 원칙적으로 SELECT 에서 지정한 별칭을 사용할 수 없지만, MySQL이나 특정 DB에서는 이를 허용해준다.
-- WHERE 과 차이점은 WHERE은 그룹핑이 되기 전에 가져올 행을 필터링하고,
-- HAVING은 그룹핑 후 가져올 그룹을 필터링 한다.
-- 그래서 WHERE 절에서는 age > 20 처럼 그룹으로 묶기전 기본적으로 거를 데이터를 정할 수 있고,
-- GROUP BY 절에서는 WHERE 절에서 필터링한 행들만 가지고 그룹을 만들게 된다.
-- 그 후 HAVING 절에서는 각 그룹별로 조건을 검사해 최종적으로 남을 그룹들을 선별하게 된다.