프로그래머스 SQL 고득점 kit
1. SELECT 부분
- ORDER BY 옵션에는 ASC 와 DESC가 있다. 내림차순이 4글자인걸 기억하자.
- WHERE 사용법
- WHERE column = 'data' : 동일할 때
- WHERE column != 'data' : 다를 때
- WHERE column is NULL : NULL값일 때
- WHERE column is not NULL : NULL이 아닐 때
2. SUM, MAX, MIN 부분
- 갯수 세기
- SELECT COUNT(*) FROM DATE_TABLE; : 이렇게 세고자 하는 대상에 COUNT()를 사용해주면 된다.
- SELECT COUNT( DISTINCT * ) FROM DATA_TABLE; : 이렇게 하면 유일값 기준으로 갯수를 세준다.
3. GROUP BY 부분
- 조건부 그룹
- 보통 조건을 넣어줄 때 WHERE를 사용했지만 GROUP BY 부분에서는 다르다.
- GROUP BY column HAVING condition; : HAVING 절로 조건을 달 수 있다.
* SQL에서 조건을 사용할 때
: 파이썬처럼 0<=X<20 하면 안된다.
-> 0 <= X AND X < 20 이렇게 작성하길.
- DATETIME 활용법
- DATETIME 데이터에 YEAR, MONTH, DAY, HOUR, MINUTE, SECOND 를 함수로 적용하면 해당 값을 얻을 수 있다.
- SET 활용 [ 입양 시각 구하기 (2) ]
: SQL에서 변수를 활용해보자.
SET @HOUR = -1;
SELECT (@HOUR := @HOUR + 1) AS HOUR
FROM ANIMAL_OUTS;
1. HOUR 라는 변수를 생성하고
2. ANIMAL_OUTS의 ROW 갯수만큼 HOUR 컬럼을 생성하는데, 컬럼의 ROW값에 1씩 더해가는 형태이다.
결과적으로 이렇게 0~99까지 (ANIMAL_OUTS의 열 갯수가 100개이다.)
HOUR라는 컬럼에 ROW가 생성된다.
이제 이걸 문제풀이에 활용해보자.
SELECT ... FROM ... 의 특징은
FROM 뒤에 있는 데이터에 기반하여
SELECT 뒤에 있는 column에 기반한
데이터 테이블을 생성한다고 생각하면 좋다.
- 서브쿼리 (Subquery)
: 하나의 SQL문 안에 포함되어 있는 또 다른 SQL문.
SELECT *
FROM db_table
WHERE table_fk IN (
#서브쿼리
SELECT table_fk FROM db_table_other WHERE ..
)
이제 위 두가지 개념을 합하여 문제를 해결해보자.
SET @HOUR = -1;
SELECT
(@HOUR := @HOUR + 1) AS HOUR,
(SELECT COUNT(*)
FROM ANIMAL_OUTS
WHERE @HOUR = HOUR(DATETIME)) AS COUNT
FROM ANIMAL_OUTS
WHERE @HOUR < 23;
두개의 컬럼을 만든다.
하나는 HOUR 변수
하나는 서브쿼리
@HOUR := @HOUR +1 은 PYTHON에서 HOUR += 1 과 같은 의미라고 생각하면 된다.
컬럼 하나를 생성할 때마다 1 씩 더해진다.
그리고 이와 동일한 수(시간)을 가진 ROW만 기존 테이블에서 COUNT한 뒤 두번째 컬럼으로 넣어준다.
문제에서 22시까지 요구했기에 WHERE로 제한해준다.
이런 식으로 진행된 풀이이다. 여태 풀었던 문제 중에 가장 어려웠다.
4. IS NULL 부분
- IS NULL : NULL은 다른 값들과 다르다. NULL == NULL 은 False이다. 즉 다른 값들 처럼 연산하면 안된다.
때문에 별도의 연산기능이 있는데 그게 IS NULL 이다. NULL 여부를 판단할 대 사용하면 된다.
- IS NOT NULL : 부정형은 이렇게 쓴다.
- IFNULL(column, 'data') : column을 불러올 때 null값을 대체하고 싶다면 이렇게 진행하면 된다. 이건 sql 클라이언트마다 차이가 좀 있다. (ISNULL, NVL 등..) 내가 사용하는 MYSQL에서는 IFNULL이다! 개인적으로 이게 더 직관적이라고 생각한다.
5. JOIN 부분
- 대부분의 연산은 LEFT JOIN으로 진행된다고 했다. (생활코딩)
자, 다음과같은 데이터를 얻고싶다면 어떻게 해야할까?
A, B를 LEFT JOIN한 후에 교집합 부분을 제외하면 된다.
교집합 부분에는 A테이블에 존재하는 컬럼에 NULL이 대응하기때문에 그 NULL을 기준으로 정리하면 된다.
- SELECT * FROM table1 LEFT JOIN table2 ON table1.id = table2.id
WHERE (null인 A테이블의 컬럼 중 하나) IS NULL;
- DATETIME 데이터도 =, >, < 등의 연산이 가능하다.
- LEFT(data, stop) : 문자열 슬라이싱 방법이다.
- LEFT(data, start, stop) : 이렇게도 가능하다.
물론 RIGHT도 가능하다.
- SUBSTRING_INDEX(data, delimiter, counter) : 이 형태는, delimiter가 counter번째 나올 때까지 끊어준다. 이는 인덱스처럼 동작하기 때문에 -1, -2도 입력 가능하다.
6. STRING, DATE 부분
- IN (list) : WHERE 절에서 여러개의 값과 비교하고 싶을 때 사용하면 좋다.
EX) WHERE column IN (data1, data2, data3)
- LOCATE("string", column) : colimn에 string이 존재하는지 여부를 판단할 때 사용하면 좋다.
- IF(condition, value_if_true, value_if_false) : 조건에 따른 값을 입력하고 싶을 때 사용한다. SQL판 IF문.
- LEFT(DATE(INS.DATETIME), 10) AS "날짜" : datatime 데이터에서 년, 월, 일을 추출하라는 문제에서 내가 했던 방법이다. 답은 맞았지만 완전히 틀렸다 ㅋㅋㅋ
: datetime 데이터에는 DATE_FORMAT이라는 함수를 사용할 수 있는데, 인자로 datetime데이터와 형식을 받는다.
다음이 형식 연산자이다.
%a | Abbreviated weekday name (Sun to Sat) |
%b | Abbreviated month name (Jan to Dec) |
%c | Numeric month name (0 to 12) |
%D | Day of the month as a numeric value, followed by suffix (1st, 2nd, 3rd, ...) |
%d | Day of the month as a numeric value (01 to 31) |
%e | Day of the month as a numeric value (0 to 31) |
%f | Microseconds (000000 to 999999) |
%H | Hour (00 to 23) |
%h | Hour (00 to 12) |
%I | Hour (00 to 12) |
%i | Minutes (00 to 59) |
%j | Day of the year (001 to 366) |
%k | Hour (0 to 23) |
%l | Hour (1 to 12) |
%M | Month name in full (January to December) |
%m | Month name as a numeric value (00 to 12) |
%p | AM or PM |
%r | Time in 12 hour AM or PM format (hh:mm:ss AM/PM) |
%S | Seconds (00 to 59) |
%s | Seconds (00 to 59) |
%T | Time in 24 hour format (hh:mm:ss) |
%U | Week where Sunday is the first day of the week (00 to 53) |
%u | Week where Monday is the first day of the week (00 to 53) |
%V | Week where Sunday is the first day of the week (01 to 53). Used with %X |
%v | Week where Monday is the first day of the week (01 to 53). Used with %x |
%W | Weekday name in full (Sunday to Saturday) |
%w | Day of the week where Sunday=0 and Saturday=6 |
%X | Year for the week where Sunday is the first day of the week. Used with %V |
%x | Year for the week where Monday is the first day of the week. Used with %v |
%Y | Year as a numeric, 4-digit value |
%y | Year as a numeric, 2-digit value |
2022-02-23의 형태로 출력하고 싶다면
DATE_FORMAT(DATETIME, '%Y-%m-%d') 하면 된다.