SELECT 문에서는 결과의 정렬을 위한 ORDER BY, 결과의 개수를 제한하는 LIMIT, 중복된 데이 터를 제거하는 DISTINCT 등을 사용할 수 있다.
그리고 GROUP BY 절은 지정한 열의 데이터들을 같은 데이터끼리는 묶어서 결과를 추출한다. 주로 그룹으로 묶는 경우는 합계, 평균, 개수 등을 처리할 때 사용하므로 집계 함수와 함께 사용된다. GROUP BY 절에서도 HAVING 절을 통해 조건식을 추가할 수 있다. HAVING 절은 WHERE 절과 비슷해 보이지만, GROUP BY 절과 함께 사용되는 것이 차이점이다.
SELECT 절의 형식은 다음과 같다. 이 중에서 아직 다루지 않은 ORDER BY와 LIMIT에 대해 서 먼저 살펴보고 잠시 후에 GROUP BY, HAVING에 대해서 알아보자.
SELECT 열_이름
FROM 테이블_이름
WHERE 조건식
GROUP BY 열_이름
HAVING 조건식
ORDER BY 열_이름
LIMIT 숫자
ORDER BY 절은 결과의 값이나 개수에 대해서는 영향을 미치지 않지만, 결과가 출력되는 순서를 조절한다. 데뷔 일자(debut_date)가 빠른 순서대로 출력되었습니다.
SELECT mem_id, mem_name, debut_date
FROM member
ORDER BY debut_date;
데뷔 일자(debut_date)가 늦은 순서대로 정렬하려면 어떻게 해야할까? 간단히 제일 뒤에 DESC라고 붙여주면된다. 기본값은 ASC인데 Ascending의 약자로 오름차순을 의미하고, DESC는 Descending의 약자로 내림차순을 의미한다.
SELECT mem_id, mem_name, debut_date
FROM member
ORDER BY debut_date DESC;
ORDER BY절과 WHERE 절은 함께 사용할 수 있습니다. 평균 키(height)가 164 이상인 증류 키가 큰 순서대로 조회해보자. 그런데 오류가 발생함. 이유는 SQL 구문의 순서가 틀렸기 때문!
SELECT mem_id, mem_name, debut_date, height
FROM member
ORDER BY height DESC
WHERE height >= 164; → 오류 발생
ORDER BY 절은 WHERE 다음에 나와야한다. 다음과 같이 수정하고 다시 실행해보자. 평균 키 (height)가 164 이상인 회원들이 키가 큰 순서대로 출력되었다.
SELECT mem_id, mem_name, debut_date, height
FROM member
WHERE height >= 164
ORDER BY height DESC;
하지만 한 가지 더 고려할 사항이 있다. 잇지와 트와이스의 평균키(height)는 167로 동일한데 잇지가 먼저 출력되었음. 트와이스 입장에서는 자신들이 데뷔 일자(debut_date)가 더 빠르므로 먼저 나와야 된다고 생각할 수 있다.
정렬 기준은 1개 열이 아니라 여러 개 열로 지정할 수 있다. 우선 첫 번째 지정 열로 정렬한 후에 동일할 경우에는 다음 지정 열로 정렬할 수 있다. 즉, 평균 키가 큰 순서대로 정렬하되, 평균 키 가 같으면 데뷔 일자가 빠른 순서로 정렬한다.
SELECT mem_id, mem_name, debut_date, height
FROM member
WHERE height >= 164
ORDER BY height DESC, debut date ASC;
LIMIT 형식은 LIMIT 시작, 개수이다. 지금과 같이 LIMIT 3만 쓰면 LIMIT 0, 3과 동일합니다. 즉, 0번째부터 3건이라는 의미.
SELECT men name, debut date
FROM member
ORDER BY debut date
LIMIT 3;
필요하다면 중간부터 출력도 가능. 다음과 같이 평균키(height)가 큰 순으로 정렬하되, 3번 째부터 2건만 조회할 수 있다.
SELECT menti nane, height
FROM member
ORDER BY height DESC
LIMIT 3, 2;
LIMIT 시작, 개수는 LIMIT 개수 OFFSET 시작이라고 쓰는 것과 동일. 또한 UMIT는 첫 데이터를 0번으로 설정하고 시작.
DISTINCT는 조회된 결과에서 중복된 데이터를 1개만 남김. 여기서는 회원들의 지역(addr)을 출력해보자.
다음 SQL의 결과를 보면 회원이 사는 지역(addr)은 경기, 경남, 서울, 전남, 경북 등 5군데. 지금은 데이터 건수가 적은데도 중복된 것을 눈으로 골라내기가 어렵.
SELECT addr FROM member;
그럼 앞에서 배운 ORDER BY 사용. 같은 지역(addr)이 몰려 있어서 아까보다는 세기가 쉽지만 이 역시 데이터 건수가 수만 개라면 현실적을 종류 세는 것은 너무 어려움.
SELECT addr FROM ORDER BY addr;
이를 간단하게 하는 것이 DISTINCT 문. 열 이름 앞에 DISTINCT를 써주기만 하면 중복된 데이터를 1개만 남기고 제거.
SELECT DISTINCT addr FROM member;
GROUP BY 절은 말 그대로 그룹으로 묶어주는 역할. 103쪽 '인터넷 마켓 DB 구성도'를 살펴보면, 다음 SQL을 사용하면 market_db의 구매 테이블(buy)에서 회원(mem_id)이 구매 한 물품의 개수(amount)를 구할 수 있다.
회원(mem_id)별로 여러 건의 물건 구매가 있었고, 각각의 행이 별도로 출력됨. APN(에 이핑크) 회원의 경우에는 1+2+1+1=5개의 물건을 구매. 그런데 합계를 이렇게 암산이나 계산기로 계산해야 한다면 MySQL을 사용할 이유가 없을 것.
SELECT mem_id, amount FROM buy ORDER BY mem_id;
이럴 때 집계 함수 사용하면 됨. 집계 함수는 주로 GROUP BY 절과 함께 쓰이며 데이터를 그룹화(grouping)해주는 기능함.
GROUP BY와 함께 주로 사용되는 집계 함수는 다음 표와 같습니다.
각 회원(mem_id)별로 구매한 개수(amount)를 합쳐서 출력하기 위해서는 집계 함수인 SUM() 과 GROUP BY 질을 사용하면 된다. 즉, GROUP BY로 회원별로 묶어준 후에 SUM() 함수로 구매한 개수를 합치면 됨.
SELECT men_id, SUN(amount) FROM buy GROUP BY men_id;
일에서 배운 범칭을 사용해서 다음과 같이 결과를 보기 좋게 만들 수 있다.
SELECT mem_id "회원 아이디", SUM(amount) "총 구매개수"
FROM buy GROUP BY men_id;
별칭에 작은따옴표를 사용해도 되지만 작은마옴표는 INSERT 등에서 문자를 사용하므로 별칭에는 큰 따옴표를 사용할 것을 권장.
이번에는 회원이 구매한 금액의 총합을 출력. 구매한 금액은 가격(price) * 수량 (amount)이다. 역시 합계는 SUM()을 사용하면 됩니다.
SELECT dem_id "회원 아이디", SUM(price*amount) "총 구매 금액"
FROM buy GROUP BY mem_id;
전체 회원이 구매한 물품 개수(amount)의 평균을 구해보자. 즉, 회원이 한 번 구매할 때마 다 평균 몇 개를 구매하는지 알아보는 것. 평균 구에 개수의 결과는 3.0개입니다.
SELECT AVG(amount) "평균 구매 개수" FROM buy;
이번에는 각 회원이 한 번구매 시 평균 몇 개를 구매했는지 알아보자. 회원(mem_id)별로 구해야 하므로 GROUP BY를 사용하면 됨.
SELECT mem_id, AVG(amount) "평군 구매 개수"
FROM buy
GROUP BY mem_id;
이번에는 회원 테이블(member)에서 연락처가 있는 회원의 수를 카운트 해보자. 그런데 결과는 전체 회원 수인 10명이 나온다.
SELECT COUNT(*) FROM member;
연락처가 있는 회원만 카운트하려면 국번(phone1) 또는 전화번호(phone2)의 열 이름을 지정해야 한다. 그러면 NULL 값인 항목은 제외하고 카운트하여 결국 연락처가 있는 회원의 인원만 나온다. 예상한 대로 8명이 나왔다.
SELECT COUNT(phone1) "연락처가 있는 희원" FROM member;
COUNT()는 모든 개수를 세고, COUNT(열이름) 열 이름의 값이 NULL인 것을 제외한 행의 개수를 센다._
앞에서 살펴보았던 SUM()으로 회원(mem_id)별 총 구매액을 구해보자.
SELECT mem_id"회원 아이디", SUM(price*amount) "총 구매 금액"
FROM buy
GROUP BY mem_id;
결과 중에서 총 구매액이 1000 이상인 회원에게만 사은품을 증정하려면 어떻게 해야 할까? 아마도 조건을 포함하는 WHERE 절을 생각했을 것이다. 그런데 다음과 같이 실행해보니 오류가 발생한다. 오류 메시지를 보면 집계 함수는 WHERE 절에 나타날 수 없다는 내용이다.
SELECT mem_id"회원 아이디", SUM(price amount) "총 구매 금액"
FROM buy
WHERE SUM(price amount) > 1000;
GROUP BY mem id;
[오류 메시지
Error Code: 1111. Invalid use of group function]
이럴 때 WHERE 대신에 사용되는 것이 HAVING 절. HAVING은 WHERE와 비슷한 개념으로 조건을 제한하는 것이지만, 집계 함수에 대해서 조건을 제한하는 것이라고 생각하면 된다. 그리고 HAVING 절은 꼭 GROUP BY 절 다음에 나와야 한다.
SELECT mem_id "회원 아이디", SUM(price*amount) "충 구매 금액"
FROM buy
GROUP BY mem id
HAVING SUM(price amount) > 1000;
GROUP BY와 관련된 조건은 HAVING을 사용해야 한다.
만약 총 구매액이 큰 사용자부터 나타내려면 ORDER BY를 사용하면 됩니다.
SELECT men id "회원 아이디", SUM(price*amount) "총 구매 금액"
FROM buy
GROUP BY mem_id
HAVING SUM(price amount) > 1000
ORDER BY SUR(price amount) DESC;
이로써 SELECT 문과 관련된 기본적인 SQL 형식은 모두 살펴봤다.