[programmers] String, Date
조건에 부합하는 중고거래 상태 조회하기- level 2
출처 - https://school.programmers.co.kr/learn/courses/30/lessons/164672
Sol)
<hide/>
SELECT BOARD_ID ,WRITER_ID, TITLE, PRICE,
CASE STATUS
WHEN 'RESERVED' THEN '예약중'
WHEN 'DONE' THEN '거래완료'
WHEN 'SALE' THEN '판매중'
END STATUS
FROM USED_GOODS_BOARD
WHERE CREATED_DATE = "2022-10-05"
ORDER BY 1 DESC
- CASE 문 이용
대여 기록이 존재하는 자동차 리스트 구하기 - level 3
출처 - https://school.programmers.co.kr/learn/courses/30/lessons/157341
Sol)
<hide/>
WITH TMP AS
(
SELECT CAR_ID,
CASE
WHEN MONTH(START_DATE) = 10 THEN 1
END "IS_MONTH_OCT"
FROM CAR_RENTAL_COMPANY_CAR RIGHT JOIN CAR_RENTAL_COMPANY_RENTAL_HISTORY USING(CAR_ID)
WHERE CAR_TYPE = '세단'
)
SELECT CAR_ID
FROM TMP
WHERE IS_MONTH_OCT IS NOT NULL
GROUP BY CAR_ID
ORDER BY 1 DESC
- RIGHT JOIN
- DISTINCT를 넣거나 group by를 넣어서 하나의 car_id는 한 번만 출력되도록 한다.
- group by는 서브쿼리가 아니라 본 쿼리에 넣어줘야 에러가 나지 않는다.
- IS NOT NULL 을 이용해서 데이터가 있는 경우만 출력되도록 한다.
자동차 평균 대여 기간 구하기 - level 2
출처 - https://school.programmers.co.kr/learn/courses/30/lessons/157342?language=mysql
Sol)
<hide/>
with TB_DATEDIFF as
(
SELECT *, DATEDIFF(END_DATE, START_DATE) + 1 DATEDIFF
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
ORDER BY CAR_ID
), TB_AVG as
(
SELECT car_id, avg(DATEDIFF) avg
FROM TB_DATEDIFF
group by car_id
)
SELECT car_id CAR_ID, round(avg, 1) AVERAGE_DURATION
FROM TB_AVG
where avg >= 7
group by car_id having AVERAGE_DURATION >= 7
ORDER BY 2 DESC,car_id DESC
# AVG가 아닌 반올림된 값으로 정렬해야한다.
- 마지막에 정렬할 때 AVG가 아닌 ROUND()의 결괏값을 기준으로 정렬해야하는 것에 주의한다.
조건에 맞는 사용자 정보 조회하기 - level 3
출처 - https://www.youtube.com/watch?v=ErtObGJ0wWc&t=614s
Sol)
<hide/>
WITH TMP AS
(
SELECT USER_ID, NICKNAME, CONCAT(CITY, ' ', STREET_ADDRESS1,' ', STREET_ADDRESS2) 전체주소,
CONCAT(SUBSTR(TLNO, 1, 3), '-',
SUBSTR(TLNO, 4, 4), '-',SUBSTR(TLNO, 8, 4)) 전화번호,
TLNO,
COUNT(*) CNT
FROM USED_GOODS_BOARD JOIN USED_GOODS_USER ON WRITER_ID = USER_ID
GROUP BY USER_ID
)
SELECT USER_ID, NICKNAME, 전체주소, 전화번호
FROM TMP
WHERE CNT >= 3
ORDER BY 1 DESC
- CONCAT()을 이용해서 이어 붙인다.
- substr(변수명, 1, 3): 1번 인덱스부터 시작해서 3개를 가져온다.
- cf)
- (Java에서는 substring을 이용할 때, 시작 인덱스, 끝 인덱스를 넣는 것과는 다르게 마지막 파라미터에 끝 인덱스가 아닌 끝 인덱스를 넣어준다. )
- (그리고 인덱스는 0이 아닌 1부터 시작하는 것에 주의한다.)
자동차 대여 기록에서 장기/단기 대여 구분하기 - level 1
출처 - https://school.programmers.co.kr/learn/courses/30/lessons/151138
Sol)
<hide/>
SELECT HISTORY_ID, CAR_ID,
DATE_FORMAT(START_DATE, '%Y-%m-%d') START_DATE,
DATE_FORMAT(END_DATE, '%Y-%m-%d') END_DATE,
CASE
WHEN DATEDIFF(END_DATE, START_DATE) + 1 >= 30 THEN '장기 대여'
ELSE '단기 대여'
END 'RENT_TYPE'
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
WHERE
YEAR(START_DATE) = 2022 AND
MONTH(START_DATE) = 9
ORDER BY HISTORY_ID DESC
- 주의할 점은 대여 기간은 시작일, 끝일을 포함해야한다는 점이다.
따라서 datediff는 차이 + 1을 해줘야한다. - datediff 는 end_date - start_date + 1로 설정한다.
- date_format 을 이용해서 포맷을 바꿔준다.
취소되지 않은 진료 예약 조회하기 - level 4
출처 - https://school.programmers.co.kr/learn/courses/30/lessons/132204
Sol)
<hide/>
SELECT APNT_NO, PT_NAME, PT_NO, A.MCDP_CD, DR_NAME, APNT_YMD
FROM PATIENT JOIN APPOINTMENT A USING (PT_NO)
JOIN DOCTOR ON DR_ID = MDDR_ID
WHERE YEAR(APNT_YMD) = 2022 AND MONTH(APNT_YMD) = 4 AND DAY(APNT_YMD) = 13
AND APNT_CNCL_YN = 'N'
ORDER BY APNT_YMD
- 취소 여부가 "N"에 해당하면서 날짜 조건에 맞는 데이터만 가져온다.
조건별로 분류하여 주문 상태 출력하기 - level 3
출처 - https://school.programmers.co.kr/learn/courses/30/lessons/131113
Sol)
<hide/>
SELECT ORDER_ID, PRODUCT_ID,
DATE_FORMAT(OUT_DATE, "%Y-%m-%d") OUT_DATE,
CASE
WHEN OUT_DATE <= "2022-05-01" THEN "출고완료"
WHEN OUT_DATE > "2022-05-01" THEN "출고대기"
ELSE "출고미정"
END "출고여부"
FROM FOOD_ORDER
ORDER BY ORDER_ID
- CASE문을 이용해서 날짜에 따라 출고 상태를 출력한다.
자동차 대여 기록 별 대여 금액 구하기 - level 4
출처 - https://school.programmers.co.kr/learn/courses/30/lessons/151141
Sol)
<hide/>
WITH TB_DATEDIFF AS
(
SELECT *, DATEDIFF(END_DATE, START_DATE) + 1 DATEDIFF
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY JOIN CAR_RENTAL_COMPANY_CAR USING (CAR_ID)
WHERE CAR_TYPE = '트럭'
)
SELECT HISTORY_ID,
CASE
WHEN DATEDIFF >= 90 THEN ROUND(DAILY_FEE * (1 - 0.15) * DATEDIFF , 0)
WHEN DATEDIFF >= 30 THEN ROUND( DAILY_FEE * (1 - 0.08) * DATEDIFF,0)
WHEN DATEDIFF >= 7 THEN ROUND(DAILY_FEE * (1 - 0.05) * DATEDIFF, 0)
ELSE DAILY_FEE * DATEDIFF
END AS FEE
FROM TB_DATEDIFF
GROUP BY 1
ORDER BY 2 DESC, 1 DESC
- 세 테이블 중 한 테이블은 JOIN 에 사용하지 않고 CASE문에 직접 데이터를 넣어줬다.
- 문제의 예시와 테스트 케이의 테이블을 출력해보면 다르게 할인율이 다르다. 그래서 SELECT * FROM PLAN 을 한 다음에 할인율을 확인한 다음에 그에 맞춰서 CASE 문에 할인율을 넣어줬다.
- 그런데 만약, 위 경우와 다르게 데이터가 복잡한 경우에는 위의 duration_type과 할인율을 매치하는 방법을 생각해봐야할 것 같다.
조회수가 가장 많은 중고 거래 게시판의 첨부 파일 조회하기 - level 3
출처 - https://school.programmers.co.kr/learn/courses/30/lessons/164671
Sol)
<hide/>
SELECT concat('/home/grep/src/',board_id, '/' , FILE_ID, FILE_NAME, FILE_EXT) FILE_PATH
FROM USED_GOODS_FILE
where board_id = (
SELECT BOARD_ID
FROM USED_GOODS_BOARD join USED_GOODS_FILE using(BOARD_ID)
group by BOARD_ID
order by VIEWS desc
LIMIT 1
)
order by 1 desc
- CONCAT() 을 이용해서 이어 붙인다.
- 조횟수가 가장 높은 게시물은 order by, limit를 이용해서 가져온다. 또는 max()를 이용해서 가져올 수도 있다.
특정 옵션이 포함된 자동차 리스트 구하기 - level 1
출처 - https://school.programmers.co.kr/learn/courses/30/lessons/157343
Sol)
<hide/>
SELECT *
FROM CAR_RENTAL_COMPANY_CAR
WHERE OPTIONS LIKE('%네비게이션%')
ORDER BY 1 DESC
- LIKE()를 이용해서 네비게이션이 포함된 차를 가져온다.
루시에 엘라 찾기- level 2
출처 - https://school.programmers.co.kr/learn/courses/30/lessons/59046
Sol)
<hide/>
SELECT ANIMAL_ID, NAME, SEX_UPON_INTAKE
FROM ANIMAL_INS
WHERE NAME IN ('Lucy','Ella','Pickle', 'Rogan', 'Sabrina', 'Mitty')
ORDER BY 1
- NAME이 해당 리스트에 있는지 IN()으로 조건을 넣어준다.
이름에 el이 들어가는 동물 찾기- level 2
출처 - https://school.programmers.co.kr/learn/courses/30/lessons/59047
Sol)
<hide/>
SELECT ANIMAL_ID, NAME
FROM ANIMAL_INS
WHERE NAME LIKE('%EL%') AND ANIMAL_TYPE = 'Dog'
ORDER BY NAME
- LIKE()
중성화 여부 파악하기 - level 2
출처 - https://school.programmers.co.kr/learn/courses/30/lessons/59409
Sol)
<hide/>
SELECT ANIMAL_ID, NAME,
CASE
WHEN SEX_UPON_INTAKE LIKE('%Neutered%') OR SEX_UPON_INTAKE LIKE('%Spayed%') THEN "O"
ELSE "X"
END AS "중성화"
FROM ANIMAL_INS
ORDER BY ANIMAL_ID
- "spayed" 포함 여부에 따라 중성화 여부를 판단하고 case 문으로 나눈다.
오랜 기간 보호한 동물 (2) - level 3
출처 - https://school.programmers.co.kr/learn/courses/30/lessons/59411
Sol)
<hide/>
WITH TMP AS
(
SELECT OUTS.ANIMAL_ID OUT_ID, OUTS.NAME OUT_NAME, INS.DATETIME IN_DT, OUTS.DATETIME OUT_DT, OUTS.DATETIME - INS.DATETIME DIFF
FROM ANIMAL_INS INS RIGHT JOIN ANIMAL_OUTS OUTS USING (ANIMAL_ID)
WHERE OUTS.ANIMAL_ID IS NOT NULL
)
SELECT OUT_ID, OUT_NAME
FROM TMP
ORDER BY DIFF DESC
LIMIT 2
- RIGHT JOIN
카테고리별 상품 개수 구하기 - level 2
출처 - https://school.programmers.co.kr/learn/courses/30/lessons/131529
Sol)
<hide/>
SELECT SUBSTR(PRODUCT_CODE, 1, 2) CATEGORY, COUNT(*)
FROM PRODUCT
GROUP BY CATEGORY
ORDER BY 1
- SUBSTR()
- COUNT()
DATETIME에서 DATE로 형변환 - level 2
출처 - https://school.programmers.co.kr/learn/courses/30/lessons/59414
Sol)
<hide/>
SELECT ANIMAL_ID, NAME, date_format(DATETIME, '%Y-%m-%d') 날짜
FROM ANIMAL_INS
order by ANIMAL_ID
- date_format() 으로 반드시 형변환 해줘야한다.