SELECT문
SELECT select_list [ INTO new_table ]
[ FROM table_source ] [ WHERE search_condition ]
[ GROUP BY group_by_expression ]
[ HAVING search_condition ]
[ ORDER BY order_expression [ ASC | DESC ] ]
- INTO : 조건에 맞는 기존 테이블의 열 내용을 새 테이블로 가져와 테이블을 만드는 것
- GROUP BY : 그룹
- ORDER BY : 정렬
- HAVING: 특정 컬럼을 그룹화한 결과에 조건을 걸 때 사용
- WHERE는 그룹화 하기 전, HAVING은 그룹화 한 후에 조건
프로그래머스 예제
1. 모든 동물의 정보를 ANIMAL_ID 순으로 조회
SELECT * FROM ANIMAL_INS ORDER BY ANIMAL_ID ASC;
SELECT NAME,DATETIME FROM ANIMAL_INS ORDER BY ANIMAL_ID DESC;
SELECT ANIMAL_ID,NAME FROM ANIMAL_INS ORDER BY ANIMAL_ID ASC;
SELECT ANIMAL_ID,NAME,DATETIME FROM ANIMAL_INS ORDER BY NAME ASC, DATETIME DESC;
2. 특정 조건을 만족하는 동물의 특정 열의 정보를 조회
SELECT ANIMAL_ID, NAME FROM ANIMAL_INS WHERE INTAKE_CONDITION = 'Sick';
SELECT ANIMAL_ID, NAME FROM ANIMAL_INS WHERE INTAKE_CONDITION != 'Aged';
3. 특정 열에 대한 상위 n개의 동물의 특정 열의 정보를 조회
SELECT NAME FROM ANIMAL_INS ORDER BY DATETIME ASC LIMIT 1;
SELECT DATETIME FROM ANIMAL_INS ORDER BY DATETIME DESC LIMIT 0,1;
SELECT DATETIME FROM ANIMAL_INS ORDER BY DATETIME ASC LIMIT 0,1;
집계함수
COUNT: 원하는 데이터의 갯수 추출
테이블 전체의 행 숫자를 알고 싶다면 COUNT(*)
특정 열의 숫자를 확인하려면 COUNT(열)
1) NULL 값이 포함되면 count하지 않는다.
2) 중복값은 포함해서 집계한다. -> 중복값을 제외하고 count하기 위해서는 DISTINCT 사용
COUNT(DISTINCT 열)
SUM
AVG
MIN
MAX
프로그래머스 예제
SELECT MAX(DATETIME) FROM ANIMAL_INS;
SELECT DATETIME FROM ANIMAL_INS ORDER by DATETIME DESC Limit 1;
SELECT MIN(DATETIME) FROM ANIMAL_INS;
SELECT DATETIME FROM ANIMAL_INS ORDER BY DATETIME ASC LIMIT 0,1;
SELECT COUNT(* FROM ANIMAL_INS ;
SELECT COUNT(DISTINCT NAME) FROM ANIMAL_INS ;
GROUP BY
- 구하려는 값이 전체 행의 갯수가 아닌 그룹별로 집계하려고 할 때 사용
- 그룹으로 묶는 컬럼이 아닌 다른 컬럼은 SELECT 문에 포함되면 안된다.
SELECT 컬럼 FROM 테이블 GROUP BY 그룹화할 컬럼 HAVING 조건식
프로그래머스 예제
1. 고양이와 개가 각각 몇 마리인지 조회
SELECT ANIMAL_TYPE, COUNT(ANIMAL_TYPE) FROM ANIMAL_INS
GROUP BY ANIMAL_TYPE
ORDER BY ANIMAL_TYPE ASC;
2. 동물 이름 중 두번 이상 쓰인 이름과 해당 이름이 쓰인 횟수, 이름은 순으로 조회
SELECT NAME, COUNT(*) AS 'COUNT'
FROM ANIMAL_INS
WHERE NAME IS NOT NULL
GROUP BY NAME
HAVING COUNT('COUNT') > 1
ORDER BY NAME ASC;
3. 각 시간대별로 입양이 몇 건 발생 했는지 시간대순으로 정렬
SELECT HOUR(DATETIME) AS 'HOUR', COUNT(HOUR(DATETIME)) AS 'COUNT' FROM ANIMAL_OUTS
GROUP BY HOUR
HAVING HOUR >=9 AND HOUR < 20
ORDER BY HOUR ASC;
4. 각 시간대 별로 입양이 발생한 건수를 시간대순으로 정렬
- 재귀문 사용해서 NULL 값들도 표현
WITH RECURSIVE cte AS (
SELECT 0 AS HOUR
UNION ALL
SELECT HOUR+1 FROM cte
WHERE HOUR < 23
)
SELECT HOUR, COUNT(HOUR(DATETIME)) as 'COUNT' from cte
LEFT OUTER JOIN (ANIMAL_OUTS)
ON HOUR(DATETIME) = HOUR
GROUP BY HOUR
ORDER BY HOUR
JOIN
- JOIN은 데이터베이스 내의 여러 테이블에서 가져온 레코드를 조합하여 하나의 테이블이나 결과 집합으로 표현해준다.
1. INNER JOIN
- INNER JOIN은 ON 절과 함께 사용되며, ON 절의 조건을 만족하는 데이터만을 가져온다.
- ON절에서는 WHERE 절에서 사용할 수 있는 모든 조건을 사용할 수 있다.
- A와 B의 교집합
2. LEFT JOIN
- LEFT JOIN은 첫번째 테이블을 기준으로 두번째 테이블을 조합하는 JOIN
- ON 절의 조건을 만족하지 않는 경우에는 첫 번째 테이블의 필드 값을 그대로 가져온다. 하지만 해당 레코드의 두번째 테이블의 필드 값은 모두 NULL로 표시된다.
3. RIGHT JOIN
- RIGHT JOIN은 두번째 테이블을 기준으로 첫번째 테이블을 조합하는 JOIN
- ON 절의 조건을 만족하지 않는 경우에는 두번째 테이블의 필드 값을 그대로 가져온다. 하지만 해당 레코드의 첫번째 테이블의 필드 값은 모두 NULL로 표시된다.
프로그래머스 예제
1.
SELECT ANIMAL_OUTS.ANIMAL_ID,ANIMAL_OUTS.NAME FROM ANIMAL_OUTS
LEFT JOIN ANIMAL_INS ON
ANIMAL_OUTS.ANIMAL_ID = ANIMAL_INS.ANIMAL_ID
WHERE ANIMAL_INS.ANIMAL_ID IS NULL
ORDER BY ANIMAL_ID
- 테이블명.컬럼값 으로 접근 가능
2.
-- 코드를 입력하세요
SELECT ANIMAL_OUTS.ANIMAL_ID, ANIMAL_OUTS.NAME FROM ANIMAL_OUTS
LEFT JOIN ANIMAL_INS ON
ANIMAL_OUTS.ANIMAL_ID = ANIMAL_INS.ANIMAL_ID
WHERE ANIMAL_INS.DATETIME > ANIMAL_OUTS.DATETIME
ORDER BY ANIMAL_INS.DATETIME ASC;
- 처음에 LEFT JOIN ANIMAL_OUTS ON 으로 작성하였더니
Not unique table/alias: 'ANIMAL_OUTS' 이런 오류가 나왔다.
SELECT (열) FROM (첫번째 Table) LEFT JOIN (두번째 Table)
3. 아직 입양을 못 간 동물 중 가장 오래 보호소에 있었던 동물 3마리의 이름과 보호 시작일 조회
- 들어온 동물의 정보를 담은 테이블(INS) 기준에서 입양보낸 동물의 정보를 빼면(OUTS) 입양 못 간 동물들이 나온다.
- 이 중 DATETIME이 가장 낮은(오래전부터 있던) 동물 3마리 조회
SELECT ANIMAL_INS.NAME, ANIMAL_INS.DATETIME FROM ANIMAL_INS
LEFT JOIN ANIMAL_OUTS ON
ANIMAL_INS.ANIMAL_ID = ANIMAL_OUTS.ANIMAL_ID
WHERE ANIMAL_OUTS.DATETIME IS NULL
ORDER BY ANIMAL_INS.DATETIME ASC LIMIT 3
4. 보호소에 들어올 당시에는 중성화 되지 않았지만, 보호소를 나갈 당시에 중성화된 동물의 아이디와 생물 종, 이름을 아이디 순으로 조회
- SEX_UPON_INTAKE에서는 Intact이라는 말이 들어가 있지만, SEX_UPON_OUTCOME에는 Intact라는 말이 없다
(중성화되면 Neutered Male, Spayed Female로 표현되어 있음)
SELECT ANIMAL_INS.ANIMAL_ID, ANIMAL_INS.ANIMAL_TYPE, ANIMAL_INS.NAME FROM ANIMAL_INS
LEFT JOIN ANIMAL_OUTS ON
ANIMAL_INS.ANIMAL_ID = ANIMAL_OUTS.ANIMAL_ID
WHERE ANIMAL_INS.SEX_UPON_INTAKE LIKE 'Intact%' AND
ANIMAL_OUTS.SEX_UPON_OUTCOME NOT LIKE 'Intact%'
ORDER BY ANIMAL_INS.ANIMAL_ID ASC;
WHERE
WHERE 조건1 AND 조건2
WHERE 조건1 OR 조건2
WHERE NOT 조건
WHERE 컬럼명 LIKE '특정문자열'
- LIKE, NOT LIKE
- '%' : 임의의 문자 또는 문자열, 빈 문자열
%VALUE : VALUE로 끝나는 값, VALUE% : VALUE로 시작하는 값, %VALUE% : VALUE가 들어가는 값
- '_' : 임의의 문자 한 개
String, Date
CASE문
-형식
CASE 컬럼
WHEN 조건1 THEN 값1
WHEN 조건2 THEN 값2
ELSE 값3
END
-사용
약어나 코드를 읽기 쉬운 값으로 바꿔줄 때
데이터를 범주화 할 때
프로그래머스 예제
1. 동물보호소에 들어온 동물 중 이름이 XXX인 동물의 아이디와 이름, 성별 및 중성화 여부를 조회
SELECT ANIMAL_ID, NAME, SEX_UPON_INTAKE FROM ANIMAL_INS
WHERE NAME LIKE 'Lucy' OR
NAME LIKE 'Ella' OR
NAME LIKE 'Pickle' OR
NAME LIKE 'Rogan' OR
NAME LIKE 'Sabrina' OR
NAME LIKE 'Mitty'
SELECT ANIMAL_ID, NAME, SEX_UPON_INTAKE
FROM ANIMAL_INS
where name in ('Lucy', 'Ella', 'Pickle', 'Rogan', 'Sabrina', 'Mitty');
2. 이름이 el이 들어가는 개의 아이디와 이름을 조회
SELECT ANIMAL_ID,NAME FROM ANIMAL_INS
WHERE NAME LIKE '%el%' AND ANIMAL_TYPE LIKE 'Dog'
ORDER BY NAME ASC;
- ANIMAL_TYPE = 'dog' 로 해도 됨.
3. 동물의 아이디와 이름, 중성화 여부를 아이디 순으로 조회
- 중성화 되어있다면 'O', 아니면 'X'
SELECT ANIMAL_ID, NAME,
CASE
WHEN SEX_UPON_INTAKE LIKE 'Intact%' THEN 'X'
ELSE 'O'
END AS '중성화'
FROM ANIMAL_INS
ORDER BY ANIMAL_ID
4. 입양을 간 동물 중, 보호 기간이 가장 길었던 동물 두 마리의 아이디와 이름을 보호 기간이 긴 순으로 조회
- ORDER BY 하고 보호기간 순 적기
SELECT ANIMAL_OUTS.ANIMAL_ID, ANIMAL_OUTS.NAME FROM ANIMAL_OUTS
INNER JOIN ANIMAL_INS
ON ANIMAL_OUTS.ANIMAL_ID = ANIMAL_INS.ANIMAL_ID
ORDER BY ANIMAL_OUTS.DATETIME - ANIMAL_INS.DATETIME DESC LIMIT 2;
5. DATETIME->DATE 형 변환
SELECT ANIMAL_ID, NAME, DATE_FORMAT(DATETIME, '%Y-%m-%d') FROM ANIMAL_INS
ORDER BY ANIMAL_ID;
기타
IFNULL(NAME, 'No name') // 만약 NAME값이 NULL이라면, No name으로 설정하기