DML에서 select는 너무 자주 사용되는 쿼리문이다. 그래서 이를 한번 싹~ 정리해보고자 포스팅을 작성한다.
우선 Select의 기본 사용법은 아래와 같다.
SELECT <select_columns>
FROM <table>
[ WHERE condition ]
[ GROUP BY <column_name | expr | position> ]
[ HAVING condition ]
[ ORDER BY <column_name | expr | position> ];
사실 SELECT ... FROM ... WHERE 에 가장 익숙할 것이다. 가장 자주 사용하는 키워드이기 때문이다.
그래서 WHERE절에서 사용할 수 있는 조건문, GROUP BY - HAVING 절과 ORDER BY에 대해 알아볼 예정이다.
비교 연산자
비교 연산자 | 설명 |
= | 왼쪽 피연산자와 오른쪽 피연산자가 같으면 참을 반환함. |
!=, <> | 왼쪽 피연산자와 오른쪽 피연산자가 같지 않으면 참을 반환함. |
<, <=, >, >= | |
<=> | 양쪽의 피연산자가 모두 NULL이면 참을 반환하고, 하나의 피연산자만 NULL이면 거짓을 반환함. |
IS / IS NOT |
왼쪽 피연산자와 오른쪽 피연산자가 같으면 참을 반환함. (오른쪽 피연산자가 불리언 값인 TRUE, FALSE, UNKNOWN 값일 때 사용함) |
IS NULL / IS NOT NULL |
피연산자의 값이 NULL이면 참을 반환함. DNO=NULL 표현불가능. 올바른 표현 : DNO is null |
BETWEEN min AND max / NOT BETWEEN min AND max |
피연산자의 값이 min 값보다 크거나 같고, max 값보다 작거나 같으면 참을 반환함. |
IN() / NOT IN() |
피연산자의 값이 인수로 전달받은 리스트에 존재하면 참을 반환함. ex) DNO=1 OR DNO=3 == DNO IN(1,3) select name, addr from usertbl where addr NOT IN ('경남','전남','경북'); -- IN 연산자는 조건의 범위를 지정하는 데 사용된다. 값은 콤마( , )로 구분하여 괄호 내에 묶으며, 이 값 중에서 하나 이상과 일치하면 조건에 맞는 것. 기본적으로 or 개념이다. |
ANY() | - 다수의 비교값 중 한개라도 만족하면 true 이다. - IN 과 다른점은 비교 연산자를 사용한다는 점이다. SELECT * FROM emp WHERE sal = ANY(950, 3000, 1250) - 'sal = 950 OR sal = 3000 OR sal = 1250' 와 동일하다. SELECT * FROM emp WHERE sal < ANY(950, 3000, 1250) - 'sal < 950 OR sal < 3000 OR sal < 1250' 와 동일하다. |
All() | - 전체 값을 비교하여 모두 만족해야만 true 이다. SELECT * FROM emp WHERE sal = ALL(950, 3000, 1250) - 'sal = 950 AND sal = 3000 AND sal = 1250' SELECT * FROM emp WHERE sal > ALL(950, 3000, 1250) - 3000보다 큰 값만 표시된다. 'sal > 950 AND sal > 3000 AND sal > 1250' 과 동일하다 |
나이가 37세 이상인 사람을 추출.
SELECT * FROM user WHERE age >= 37;
BETWEEN...AND
BETWEEN...AND 는 데이터가 숫자로 구성되어 있어 연속적인 값 검색한다.
나이가 20살 이상부터 30살 이하인 사람들을 한 번 추출
SELECT * FROM MOCK_DATA WHERE age BETWEEN 20 AND 30;
WHERE 조건절에 적용시킬 column을 적고 숫자의 범위를 적어준다.
그럼 아래와 같은 결과값을 보여줄 수 있다.
IN 연산자
IN 연산자는 이산적인(Discrete)값 검색한다.
WHERE 문의 긴 OR를 대체할 수 있다.
데이터를 조금 추가해서 테스트를 해보자. user 데이터에 user가 속한 국가 코드를 포함시켰다.
국적이 한국인 사람(KO)과 미국(US)인 사람을 골라내고 싶으면 어떻게 해야할까?
SELECT * FROM user WHERE country_code IN ("KO", "US");
/* AND를 사용했을 경우
SELECT * FROM user WHERE country_code = "KO" OR country_code = "US";
*/
위와 같이 특정 문자열이나 숫자만을 뽑아오고 싶을 때 사용할 수 있다.
조건이 많아지면 OR로는 길고 중복되는 스트링을 확인할 수 있다.
LIKE 연산자
LIKE 연산자는 조건을 가지고 유연하게 문자열의 내용 검색할 수 있다.
만약, 검색하고자 하는 문자열의 한 글자만 무관하게 검색하고 싶다면 ' _ ' 기호를 사용하면 된다.
예를 들어 한국인의 이름들 중에서 성과는 상관없이 '태현' 이라는 이름을 가진 사람을 검색하고 싶을 때 다음과 같이 작성할 수 있다.
SELECT * FROM user WHERE name LIKE "_태현";
혹은, 여러 문자열을 무시하고 검색하고 싶을 때엔 어떻게 해야할까?
이번엔 반대로 이름과는 상관없이 '박'씨 성을 가진 사람을 검색하고 싶을 때는 다음과 같이 작성할 수 있다.
SELECT * FROM user WHERE name LIKE "박%";
위와 같이 입력하면 이름의 길이와 값에 상관없이 박씨 성을 가진 모든 사람을 검색한다.
논리 연산자
논리 연산자 | 설명 |
AND, && | 논리식이 모두 참이면 참을 반환함. |
OR, || | 논리식 중에서 하나라도 참이면 참을 반환함. |
XOR | 두 값이 같으면 거짓 두 값이 다르면 참 |
NOT, ! | 논리식의 결과가 참이면 거짓을, 거짓이면 참을 반환함. ex) where not addr = 값 |
나이가 20세 미만이거나 37살 초과인 사람 검색.
SELECT * FROM user WHERE age > 37 OR age < 20;
나이가 39세가 아닌 사람들의 데이터를 검색.
NOT은 조건 앞에 붙어 키워드 그대로 조건에 반하는 데이터를 뽑는다.
SELECT * FROM user WHERE NOT age = 39;
GROUP BY - HAVING
GROUP BY 는 말 그대로 그룹으로 묶어주는 역할을 해준다.
GROUP BY 에서는 아래와 같이 같이 사용될 수 있는 것들이 있다.
- GROUP BY
- 집계함수 Aggregate Function
- AS
- HAVING
GROUP BY
GROUP BY <column> 을 해주면 column 을 그룹으로 묶어주는 역할을 한다.
위의 데이터를 이용해서 GROUP BY에 대한 예시를 보자.
SELECT *
FROM buy
GROUP BY user_id;
위의 코드를 보면 user_id 값을 기준으로 묶은 데이터를 검색하게 된다.
그런데 이 과정에서 의문점이 하나 생기는데요, 중복되는 데이터는 어떻게 처리가 될까?
예를 들어, 위 테이블에서 Margo와 Tod는 각각 두 개의 레코드가 있다.
이 때, price와 amount의 데이터는 어떻게 처리될까?
결과를 보면 Margo, Tod와 같이 중복된 데이터는 제일 먼저 나오는 데이터가 검색되게 된다.
그럼 한 개의 데이터가 나오는 것 말고, 모든 Margo 혹은 Tod에 대한 price를 더해서 출력하고 싶으면 어떻게 해야할까?
그럴 때 집계함수를 사용하여 처리해야 한다.
집계함수 Aggregate Function
집계함수는 효율적인 데이터 그룹화를 위한 함수이다.
집계함수는 SELECT 문에 넣어 원하는 통계 값을 출력할 때 사용될 수 있다.
회원들의 구매 가격을 합으로 갖는 열을 만들어보자.
SELECT user_id, SUM(price)
FROM buy
GROUP BY user_id;
위와 같은 쿼리문을 실행시키면 아래의 'USING SUM()' 와 같은 결과를 얻을 수 있다.
user_id를 그룹으로 묶여 price에 SUM() 집계함수가 사용된 것을 확인할 수 있다.
하지만 SUM(price) 라는 열의 이름이 마음에 안든다면 이름을 바꿀 수 있다.
AS - 열 이름 지정하기
as를 사용하면 별명을 붙일 수 있다.
SELECT user_id, SUM(price) as price
FROM buy
GROUP BY user_id;
위의 결과는 아래와 같다.
이 때, as는 생략이 가능하다.
HAVING
이번에는 집계함수에 대한 조건을 주는 방법에 대해 알아보자.
HAVING 절은 사용할 때 알아둬야할 사항이 두 가지 있다.
- GROUP BY 문 뒤에 적을 수 있다.
- 집계함수에 대한 조건을 적을 수 있다.
※ 참고
WHERE 절에서는 집계함수에 대한 조건을 사용할 수 없다.
해보면 알겠지만, WHERE절은 집계함수를 인식하지 못한다.
이제 예시로 확인해보자.
만약, price의 합계가 50.0 이상인 것들을 검색하고싶다면 아래와 같은 쿼리문을 작성할 수 있다.
SELECT user_id, SUM(price) as price
FROM buy
GROUP BY user_id
HAVING price > 50;
ORDER BY
이번에는 ORDER BY에 대해 알아보고자.
ORDER BY는 이름처럼 순서를 정해주는 역할을 해준다.
ORDER BY는 기본적으로 오름차순 정렬을 보여준다.
'ORDER BY '의 형식으로, column명에는 정렬하고자 하는 열을 선택해서 넣어주면 된다.
SELECT *
FROM buy
ORDER BY user_id;
// 위와 아래가 동일
SELECT *
FROM buy
ORDER BY user_id ASC;
반대로 내림차순은 아래와 같이 작성할 수 있다.
SELECT *
FROM buy
ORDER BY user_id DESC;
위와 같이 내림차순으로 정렬하려면 'DESC' 라는 키워드를 반드시 붙여줘야한다.
DISTINCT
데이터를 검색하려고 할 때, 필요없는 중복 데이터가 계속 나오면 처리 시간만 늘어날 것이다.
중복된 데이터는 추가하지 않고 검색하려면 'DISTINCT' 키워드를 사용할 수 있다.
SELECT DISTINCT user_id
FROM buy;
위와 같이 검색하고자 하는 필드명 앞에 적어주면 중복된 데이터는 삭제하고 출력해준다.
[TEST DATA 1]과 같은 경우에는 중복된 user_id인 Margo와 Tod는 한 번씩만 출력이 된다.
LIMIT
LIMIT은 상위의 N개만 출력하는 ‘LIMIT N’ 구문을 사용한다.
일부를 보기 위해 여러 건의 데이터를 출력하는 부담 줄일 수 있다.
SELECT *
FROM buy
LIMIT 5;
위와 같은 쿼리문을 입력하게 되면 상위 0~5개의 데이터만 검색할 수 있다.
위와 같이 상위 5개만 볼 수 있게 된다.
그런데 범위를 지정해서 출력하고 싶을 때에는 어떻게 해야할까?
범위를 지정하고 싶으면 'OFFSET'을 사용하면 된다.
처음 범위를 설정해두면 LIMIT에 지정한 만큼만 뽑아서 검색하게 된다.
예를 들어 3번째 테이터부터 5개의 데이터를 추출하고 싶다면 아래와 같은 쿼리를 입력하면 된다.
(데이터는 0부터 시작)
SELECT *
FROM buy
LIMIT 5
OFFSET 3;
offset을 3으로 주면 아래와 같은 결과값이 검색된다.
LIMIT과 OFFSET은 pagination을 사용할 때 필요시 된다.