프로그래머스 SQL고득점Kit의 1~2레벨 문제
오답 개념 정리
SELECT BOOK_ID, DATE_FORMAT(PUBLISHED_DATE, '%Y-%m-%d') AS PUBLISHED_DATE
FROM BOOK
WHERE CATEGORY = '인문' AND YEAR(PUBLISHED_DATE) = 2021
ORDER BY PUBLISHED_DATE;
WHERE A.CREATED_DATE LIKE '2022-10%' --B.CREATED_DATE가 아님
SELECT IFNULL(TLNO, 'NONE') AS TLNO
ORACLE : NVL()
MYSQL : IFNULL()
GROUP BY USER_ID, PRODUCT_ID
HAVING COUNT(*) >= 2
WHERE NOT INTAKE_CONDITION = 'Aged'
WHERE INTAKE_CONDITION NOT IN ('Aged')
WHERE INTAKE_CONDITION != 'Aged'
WHERE LIMIT 1
ORACLE : ROWNUM
MYSQL : LIMIT
* ROWNUM과 LIMIT 차이
WHERE ROWNUM <= 1 -- 정렬 전 수행 ORDER BY ID;ORDER BY ID LIMIT 1; -- 정렬 후 수행
SELECT A.ITEM_ID, A.ITEM_NAME, A.RARITY
FROM ITEM_INFO AS A
JOIN ITEM_TREE AS B
ON A.ITEM_ID = B.ITEM_ID
WHERE B.PARENT_ITEM_ID IN (SELECT ITEM_ID FROM ITEM_INFO WHERE RARITY = 'RARE')
ORDER BY A.ITEM_ID DESC;
SELECT ID, EMAIL, FIRST_NAME, LAST_NAME
FROM DEVELOPERS
WHERE SKILL_CODE & (SELECT CODE FROM SKILLCODES WHERE NAME = 'C#')
OR SKILL_CODE & (SELECT CODE FROM SKILLCODES WHERE NAME = 'Python')
ORDER BY ID;
* WHERE절 설명: DEVELOPERS.SKILL_CODE & SKILLCODES.CODE WHERE NAME = 'C#'의 결과를 가지고 있는 (개발자의 코드와 이름이 C#인 코드를 & 연산 시켰더니, 나온 코드를 가지고 있는)
또는 PYTHON인 경우 마찬가지
SELECT COUNT(*) AS FISH_COUNT
FROM FISH_INFO
-- BASS 또는 SNAPPER인 컬럼 찾기
-- FISH_INFO에서 출력
WHERE FISH_TYPE = (SELECT FISH_TYPE FROM FISH_NAME_INFO WHERE FISH_NAME = 'BASS')
OR FISH_TYPE = (SELECT FISH_TYPE FROM FISH_NAME_INFO WHERE FISH_NAME = 'SNAPPER');
SELECT CONCAT(LENGTH, 'cm') AS MAX_LENGTH
SELECT CAR_TYPE, COUNT(*) AS CARS
FROM CAR_RENTAL_COMPANY_CAR
WHERE OPTIONS
-- IN ('%통풍시트%', '%열선시트%', '%가죽시트%') 불가능
LIKE '%통풍시트%' OR OPTIONS LIKE '%열선시트%' OR OPTIONS LIKE '%가죽시트%'
GROUP BY CAR_TYPE
ORDER BY CAR_TYPE ASC;
-- 문제 : 성분타입, 성분타입에 대한 총주문량
SELECT B.INGREDIENT_TYPE, SUM(A.TOTAL_ORDER) AS TOTAL_ORDER
FROM FIRST_HALF AS A
JOIN ICECREAM_INFO AS
ON A.FLAVOR = B.FLAVOR
-- 조인한 다음에, 조인된 테이블에서 B테이블에 있던 컬럼으로 조건걸기
GROUP BY B.INGREDIENT_TYPE
ORDER BY A.TOTAL_ORDER ASC;
SELECT HOUR(DATETIME) AS HOUR, COUNT(*) AS COUNT
FROM ANIMAL_OUTS
WHERE HOUR(DATETIME) >= 9 AND HOUR(DATETIME) < 20
GROUP BY HOUR(DATETIME)
ORDER BY HOUR(DATETIME);
SELECT TRUNCATE(PRICE, -4) AS PRICE, COUNT(*) AS PRODUCTS
FROM PRODUCT
-- 가격대 별로, 상품갯수
-- 가격대 정보 표시(10000~19999 : 10000)
-- 가격대로 오름차순
GROUP BY TRUNCATE(PRICE, -4)
ORDER BY TRUNCATE(PRICE, -4);
SELECT SUM(C.SCORE) AS SCORE, B.EMP_NO, B.EMP_NAME, B.POSITION, B.EMAIL
-- 평가점수가 가장 높은 사원들
-- 평가점수 : 상+하반기 점수
FROM HR_DEPARTMENT AS A
JOIN HR_EMPLOYEES AS B ON A.DEPT_ID = B.DEPT_ID
JOIN HR_GRADE AS C ON B.EMP_NO = C.EMP_NO
GROUP BY EMP_NO
ORDER BY SCORE DESC
LIMIT 1;
SELECT ROUND(SUM(IFNULL(LENGTH, 10))/COUNT(*), 2) AS AVERAGE_LENGTH
FROM FISH_INFO;
SELECT BOARD_ID, WRITER_ID, TITLE, PRICE,
CASE WHEN STATUS = 'SALE' THEN '판매중'
WHEN STATUS = 'RESERVED' THEN '예약중'
WHEN STATUS = 'DONE' THEN '거래완료'
END AS STATUS
FROM USED_GOODS_BOARD
-- WHERE 2022년 10월 5일
WHERE CREATED_DATE = '2022-10-05'
ORDER BY BOARD_ID DESC;
SELECT HISTORY_ID,
CAR_ID,
DATE_FORMAT(START_DATE, '%Y-%m-%d') AS START_DATE,
DATE_FORMAT(END_DATE, '%Y-%m-%d') AS END_DATE,
CASE WHEN ABS(DATEDIFF(START_DATE, END_DATE)) >= 29 THEN '장기 대여'
ELSE '단기 대여'
END AS RENT_TYPE
-- 2022년 9월
-- 기록ID로 내림차순
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
WHERE START_DATE LIKE '2022-09%'
ORDER BY HISTORY_ID DESC;
SELECT CAR_ID, ROUND(AVG(DATEDIFF(END_DATE, START_DATE)+1), 1) AS AVERAGE_DURATION
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
GROUP BY CAR_ID
HAVING AVG(ABS(DATEDIFF(START_DATE, END_DATE)))+1 >= 7
ORDER BY ROUND(AVG(DATEDIFF(END_DATE, START_DATE)+1), 1) DESC, CAR_ID DESC;
-- 여기서 ORDER BY절에서 ROUND()를 생략할 시 오답
SELECT
CASE
WHEN DIFFERENTIATION_DATE LIKE '%/01/%' OR DIFFERENTIATION_DATE LIKE '%/02/%' OR DIFFERENTIATION_DATE LIKE '%/03/%' THEN '1Q'
WHEN DIFFERENTIATION_DATE LIKE '%/04/%' OR DIFFERENTIATION_DATE LIKE '%/05/%' OR DIFFERENTIATION_DATE LIKE '%/06/%' THEN '2Q'
WHEN DIFFERENTIATION_DATE LIKE '%/07/%' OR DIFFERENTIATION_DATE LIKE '%/08/%' OR DIFFERENTIATION_DATE LIKE '%/09/%' THEN '3Q'
WHEN DIFFERENTIATION_DATE LIKE '%/10/%' OR DIFFERENTIATION_DATE LIKE '%/11/%' OR DIFFERENTIATION_DATE LIKE '%/12/%' THEN '4Q'
END AS QUARTER,
COUNT(*) AS ECOLI_COUNT
FROM ECOLI_DATA
-- 분기별로, 총 수
GROUP BY QUARTER
ORDER BY QUARTER;
SELECT
CASE
WHEN MONTH(DIFFERENTIATION_DATE) IN (1, 2, 3) THEN '1Q'
WHEN MONTH(DIFFERENTIATION_DATE) IN (4, 5, 6) THEN '2Q'
WHEN MONTH(DIFFERENTIATION_DATE) IN (7,8,9) THEN '3Q'
WHEN MONTH(DIFFERENTIATION_DATE) IN (10, 11, 12) THEN '4Q'
END AS QUARTER,
COUNT(*) AS ECOLI_COUNT
FROM ECOLI_DATA
-- 분기별로, 총 수
GROUP BY QUARTER
ORDER BY QUARTER;
문자열 함수 _문자를 반환
- LOWER
- UPPER
- CONCAT
- SUBSTR
- TRIM
- 참고 - IF(결과값) 출력값 : CASE문 사용
CASE WHEN 컬렴명(SIZE) 조건문(=) 결과값('SMALL') THEN 출력값('BAD') WHEN 컬럼명(SIZE) 조건문(=) 결과값('BIG') THEN 출력값('GREAT') ELSE 출력값('NO VALUE') -- ELSE 생략가능 END AS 컬럼명
숫자형 함수 _숫자를 반환
- CEIL
- FLOOR
- ROUND
- TRUNC (음수로 가면 소수점 위에 대해서도 가능)
DATE 관련 함수
- YEAR(DATE), MONTH(DATE), HOUR(DATE) : DATE 표현 함수
- DATEDIFF(DATE, DATE) : 두 DATE 사이의 일수 계산
(앞의 DATE에서 뒤의 DATE 빼기 _ABS()로 절댓값 사용하면 순서 상관X)
ex) 두 기간이 30일 이상인 경우ABS(DATEDIFF(START_DATE, END_DATE)+1) >= 30 -- DATEDIFF()+1 한 값 = 기간
기타
- IN()에서는 와일드 카드 사용 불가 -> LIKE 사용
- 조인할지 서브쿼리쓸지 -> SELECT문에 두 테이블의 컬럼을 다 쓰면 조인
(반드시 그런건 아님)- 모든 행에 대해, 모든 행의 최댓값 빼기
: 서브쿼리 이용 _SELECT문에서 (최댓값을 구한 서브쿼리)-컬럼명 가능SELECT ID, ABS(SIZE_OF_COLONY - (SELECT SIZE_OF_COLONY FROM ECOLI_DATA ORDER BY SIZE_OF_COLONY DESC LIMIT 1)) AS DEV FROM ECOLI_DATA ORDER BY DEV;
- 기타 함수..더 찾아보기
위 프로그래머스 사이트의 SQL문제에서
오라클로 작성시, 마지막줄에 주석을 작성하면 이유불명의 에러가 발생함