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) 처럼
-- 더 자세하고 구체적으로 그룹핑 할 수 있다.
- GROUP BY 주의사항
- GROUP BY 를 사용한 쿼리에서는 SELECT에서 GROUP BY 에 사용된 컬럼과 집계 함수만 사용할 수 있다.
- 예를 들어, select age, count(name) from test_table group by age; 처럼 각 그룹별로 묶고 각 그룹의 name 컬럼의 개수와 그룹핑의 기준인 age를 구하는 것은 가능하지만,
- select age, name from from test_table group by age; 처럼 name은 group by 에 적힌 컬럼이 아니므로 오류가 발생하게 된다.
- 이런식의 오류가 나는 이유는 상식적으로 각 그룹별로 묶었을 때 그룹의 기준이 아닌 컬럼을 구해야 한다면 각 그룹별로 어떤 값을 대표로 보내줘야 할지 모르기 때문에 오류가 날수밖에 없다.
- 그래서 group by 를 이용할때는 그룹의 기준이 되는 컬럼과 집계 함수 이외에는 사용하면 안된다.
- 물론 only_full_group_by 규칙을 비활성화 하면 그룹의 기준이 아닌 컬럼도 가져올 수 있지만, 이 경우 어떤 값이 나올지 애매하고 그룹핑의 의미가 사라지므로 굳이 비활성화 하지 않는 것이 좋다.
- HAVING
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 절에서는 각 그룹별로 조건을 검사해 최종적으로 남을 그룹들을 선별하게 된다.