개발자는 기록이 답이다
프로그래머스 SQL 76문제 풀기 ( 정답률 높은 순 기준 20개 ) - 4 본문
LV.2 재구매가 일어난 상품과 회원 리스트 구하기 (정답률 : 79%) 🌟🌟🌟 GROUP BY 2개
https://school.programmers.co.kr/learn/courses/30/lessons/131536
동일한 유저가 동일한 제품을 재구매 한 경우
SELECT USER_ID, PRODUCT_ID
FROM ONLINE_SALE
GROUP BY USER_ID, PRODUCT_ID
HAVING COUNT(*) >=2
ORDER BY USER_ID, PRODUCT_ID DESC;
GROUP BY 구문은 결과 집합을 사용자별(USER_ID) 및 제품별(PRODUCT_ID)로 그룹화합니다. 즉, USER_ID가 같으면서 PRODUCT_ID도 같은 컬럼을 그룹화하여 조회할 수 있습니다.
이렇게 그룹화된 결과는 사용자와 제품 간의 중복된 조합을 제거하고, 각 조합에 대한 한 번 이상의 구매 횟수를 계산하기 위해 HAVING 절에 사용됩니다.
HAVING 절은 GROUP BY로 그룹화된 결과에 대한 조건을 지정하는 데 사용됩니다. COUNT(*) >= 2라는 조건은 각 그룹(사용자와 제품 조합)에 대해 구매 횟수가 2회 이상인 그룹만 선택하도록 합니다.
즉, HAVING COUNT(*) >= 2 조건은 동일한 사용자가 동일한 제품을 두 번 이상 구매했을 경우 해당 그룹(사용자와 제품 조합)을 결과에 포함시킵니다.
HAVING 문에서는 집계함수사용 가능
- MAX : 컬럼의 최댓값을 산출
- MIN : 컬럼의 최소값을 산출
- SUM : 컬럼의 값을 합계를 산출
- COUNT : 컬럼의 갯수를 산출
- AVG : 컬럼의 평균값을 산출
- HAVING절 참고 링크
[SQL] 재구매가 일어난 상품과 회원 리스트 구하기(프로그래머스/MySQL/Level 2)
안녕하세요! 데코입니다! 오늘은 프로그래머스 코딩테스트 연습에 있는 "재구매가 일어난 상품과 회원 리스트 구하기 문제를 포스팅하려고 합니다! 바로 포스팅 시작할게요! :) (출처 : https://scho
kkw-da.tistory.com
LV.1 과일로 만든 아이스크림 고르기 (정답률 : 78%)
https://school.programmers.co.kr/learn/courses/30/lessons/133025
SELECT f.FLAVOR
FROM FIRST_HALF f JOIN ICECREAM_INFO i
ON f.FLAVOR = i.FLAVOR
WHERE i.INGREDIENT_TYPE = 'fruit_based' AND f.TOTAL_ORDER >= 3000
ORDER BY TOTAL_ORDER DESC;
LV.1 최댓값 구하기 (정답률 : 77%)
https://school.programmers.co.kr/learn/courses/30/lessons/59415
가장 최근에 들어온 동물은 언제 들어왔는지
SELECT MAX(DATETIME) AS 시간
FROM ANIMAL_INS;
LV.3 조건에 맞는 사용자 정보 조회하기 (정답률 : 77%) 🌟🌟🌟🌟🌟 CONCAT, 하이픈 , 띄어쓰기 추가
서브쿼리도 가능 참고 링크
https://school.programmers.co.kr/learn/courses/30/lessons/164670
SELECT USER_ID,
NICKNAME,
CONCAT(u.CITY,' ',u.STREET_ADDRESS1,' ',u.STREET_ADDRESS2)AS 전체주소,
CONCAT(LEFT(TLNO,3), '-', MID(TLNO,4,4),'-', RIGHT(TLNO,4)) AS 전화번호
FROM USED_GOODS_BOARD b JOIN USED_GOODS_USER u
ON b.WRITER_ID = u.USER_ID
GROUP BY u.USER_ID
HAVING COUNT(*) >= 3
ORDER BY USER_ID DESC;
SELECT USER_ID
, NICKNAME
, CONCAT(CITY, ' ', STREET_ADDRESS1, ' ', STREET_ADDRESS2) AS '전체주소'
, CONCAT(SUBSTR(TLNO, 1, 3), '-', SUBSTR(TLNO, 4, 4), '-', SUBSTR(TLNO, 8)) AS '전화번호'
FROM USED_GOODS_USER
WHERE USER_ID IN (
SELECT WRITER_ID
FROM USED_GOODS_BOARD
GROUP BY WRITER_ID
HAVING COUNT(*) >= 3
)
ORDER
BY USER_ID DESC;
MySQL 함수 [숫자열, 문자열, 집계, 날짜, 기타함수...]
MySQL 함수 숫자 관련 함수 ▶ ABS(숫자) : 절대값 출력. select abs(123); ▶ CEILING(숫자) : 값보다 큰 정수 중 가장 작은 수. --양수일 경우는 소숫점 자리에서 무조건 반올림(4.0과 같은 소숫점 자리 0 값
blog.pages.kr
LV.1 특정 옵션이 포함된 자동차 리스트 구하기 (정답률 : 75%)
https://school.programmers.co.kr/learn/courses/30/lessons/157343
SELECT CAR_ID,CAR_TYPE,DAILY_FEE,OPTIONS
FROM CAR_RENTAL_COMPANY_CAR
WHERE OPTIONS LIKE '%네비게이션%'
ORDER BY CAR_ID DESC;
LV.2 조건에 부합하는 중고거래 상태 조회하기 (정답률 : 74%) - 🌟🌟🌟 서브쿼리도 가능
https://school.programmers.co.kr/learn/courses/30/lessons/164672
SELECT BOARD_ID,
WRITER_ID,
TITLE,
PRICE,
CASE WHEN STATUS = 'SALE' THEN '판매중'
WHEN STATUS = 'RESERVED' THEN '예약중'
ELSE '거래완료' END AS STATUS
FROM USED_GOODS_BOARD
WHERE YEAR(CREATED_DATE) = '2022' AND MONTH(CREATED_DATE) = '10'AND DAY(CREATED_DATE) = '5'
ORDER BY BOARD_ID DESC;
SELECT board_id,writer_id,title, price ,
CASE WHEN status = 'SALE' THEN '판매중'
WHEN status = 'RESERVED' THEN '예약중'
WHEN status = 'DONE' THEN '거래완료' END status
FROM used_goods_board
WHERE board_id IN
(
SELECT board_id
FROM used_goods_board
WHERE created_date = '2022-10-05'
)
ORDER BY board_id DESC;
LV.3 자동차 대여 기록에서 대여중 / 대여 가능 여부 구분하기 (정답률 : 73%) - 🌟🌟🌟🌟🌟 서브쿼리!!!!(SELECT절)
https://school.programmers.co.kr/learn/courses/30/lessons/157340
SELECT CAR_ID,
(CASE WHEN CAR_ID IN (
SELECT CAR_ID
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
WHERE '2022-10-16' BETWEEN DATE_FORMAT(START_DATE, '%Y-%m-%d') AND DATE_FORMAT(END_DATE, '%Y-%m-%d'))
THEN '대여중'
ELSE '대여 가능'
END) AS 'AVAILABILITY'
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
GROUP BY CAR_ID
ORDER BY CAR_ID DESC
나는 서브쿼리로 안풀었는데, CASE WHEN절을 MAX()함수로 덮어쓰는게 중요하다
max 함수는 group by와 함께 사용해야한다. group by를 통해 car_id를 기준으로 묶어주고, 위 조건을 max함수를 통해 반환하면, 같은 car_id 중에 가장 큰 값이 실행 결과로 나타난다.
MAX를 여기에서 사용하면, 최대 값을 찾는 것이 아니라 특정 날짜('2022-10-16')에 자동차를 사용할 수 있는지 또는 임대했는지 여부를 파악할 수 있다.
-- 비교 연산자로 푸는것
SELECT CAR_ID,
MAX(CASE WHEN DATE_FORMAT(START_DATE, '%Y-%m-%d') <= '2022-10-16' AND
DATE_FORMAT(END_DATE, '%Y-%m-%d') >= '2022-10-16' THEN '대여중'
ELSE '대여 가능'
END) AS AVAILABILITY
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
GROUP BY CAR_ID
ORDER BY CAR_ID DESC;
-- between으로 푸는것
SELECT CAR_ID,
MAX(CASE WHEN '2022-10-16' BETWEEN DATE_FORMAT(START_DATE, '%Y-%m-%d')
AND DATE_FORMAT(END_DATE, '%Y-%m-%d')THEN '대여중'
ELSE '대여 가능'
END) AS 'AVAILABILITY'
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
GROUP BY CAR_ID
ORDER BY CAR_ID DESC;
LV.4 취소되지 않은 진료 예약 조회하기(정답률 : 73%) - 🌟🌟🌟
문제를 제대로 읽자.
나는 이걸 1) 취소되었는데, 취소 날짜가 2022년 4월 13일이 아닌건가 싶었는데/ 4월 23일 예약했는데 취소하지 않은 내역을 찾는 거였다
2022년 4월 13일 취소되지 않은 흉부외과(CS) 진료 예약 내역을 조회 WHERE a.APNT_YMD LIKE '2022-04-13%'
https://school.programmers.co.kr/learn/courses/30/lessons/132204
SELECT a.APNT_NO, p.PT_NAME, a.PT_NO, d.MCDP_CD, d.DR_NAME, a.APNT_YMD
FROM APPOINTMENT a JOIN PATIENT p ON a.PT_NO = p.PT_NO
JOIN DOCTOR d ON a.MDDR_ID = d.DR_ID
WHERE a.APNT_YMD LIKE '2022-04-13%'
AND A.MCDP_CD = 'CS'
AND A.APNT_CNCL_YN = 'N'
ORDER BY A.APNT_YMD ASC
LV.4 년, 월, 성별 별 상품 구매 회원 수 구하기 (정답률 : 73%) - 🌟🌟🌟
https://school.programmers.co.kr/learn/courses/30/lessons/131532
동일한 날짜, 회원 ID, 상품 ID 조합에 대해서는 하나의 판매 데이터만 존재합니다. ➡️ 중복제거 DISTINCT
COUNT(DISTINCT(u.USER_ID))
SELECT YEAR(SALES_DATE) AS YEAR, MONTH(SALES_DATE) AS MONTH, GENDER, COUNT(DISTINCT(u.USER_ID)) AS USERS
FROM USER_INFO u JOIN ONLINE_SALE s
ON u.USER_ID = s.USER_ID
WHERE GENDER IS NOT NULL
GROUP BY GENDER, YEAR(SALES_DATE), MONTH(SALES_DATE)
ORDER BY YEAR, MONTH, GENDER;
LV.4 서울에 위치한 식당 목록 출력하기 (정답률 : 72%) - 🌟
https://school.programmers.co.kr/learn/courses/30/lessons/131118
SELECT i.REST_ID, i.REST_NAME, i.FOOD_TYPE, i.FAVORITES, i.ADDRESS, ROUND(AVG(r.REVIEW_SCORE),2) AS SCORE
FROM REST_INFO i JOIN REST_REVIEW r
ON i.REST_ID = r.REST_ID
WHERE ADDRESS LIKE '서울%'
GROUP BY i.REST_ID
ORDER BY SCORE DESC
LV.2 자동차 평균 대여 기간 구하기(정답률 : 71%) - 🌟🌟🌟 DATEDIFF vs TIMESTAMPDIFF
https://school.programmers.co.kr/learn/courses/30/lessons/157342
나는 -연산자로 날짜를 빼려고 했는데 값이 엄청 크게 나오더라. 일 단위로 나오는게 아닌것같다
그래서 날짜 함수를 사용하는게 더 나을 것같다
[MYSQL] 자동차 평균 대여 기간 구하기 (프로그래머스/Level 2)
프로그래머스 코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요. programmers.co.kr 문제 설
suminii.tistory.com
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 AVERAGE_DURATION >= 7
ORDER BY AVERAGE_DURATION DESC, CAR_ID DESC;
SELECT CAR_ID,ROUND(AVG(TIMESTAMPDIFF(DAY,START_DATE,END_DATE)+1),1) AS AVERAGE_DURATION
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
GROUP BY CAR_ID
HAVING AVERAGE_DURATION >= 7
ORDER BY AVERAGE_DURATION DESC, CAR_ID DESC;
DATEDIFF vs TIMESTAMPDIFF 사용방법 차이
LV.1 자동차 대여 기록에서 장기/단기 대여 구분하기 (정답률 : 71%) - 🌟🌟
https://school.programmers.co.kr/learn/courses/30/lessons/151138
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 (DATEDIFF(END_DATE,START_DATE)+1) >= 30 THEN '장기 대여'
ELSE '단기 대여' END AS RENT_TYPE
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
WHERE START_DATE LIKE '2022-09%'
ORDER BY HISTORY_ID DESC;
LV.4 우유와 요거트가 담긴 장바구니 (정답률 : 71%) - 🌟🌟🌟 COUNT(DISTINCT(NAME))
https://school.programmers.co.kr/learn/courses/30/lessons/62284
SELECT CART_ID
FROM CART_PRODUCTS
WHERE NAME IN ('Milk', 'Yogurt')
GROUP BY CART_ID
HAVING COUNT(DISTINCT(NAME)) >= 2
ORDER BY CART_ID
GROUP BY랑 같이 쓸 수 있는 GROUP_CONCAT()
SELECT CART_ID, NAMES
FROM (
SELECT CART_ID, GROUP_CONCAT(NAME) AS NAMES
FROM CART_PRODUCTS
GROUP BY CART_ID
) TMP
WHERE NAMES LIKE '%Milk%'
AND NAMES LIKE '%Yogurt%'
#NAMES가 완전 기니까 LIKE로 찾아야함
LV.3 헤비 유저가 소유한 장소 (정답률 : 70%) - 🌟🌟 서브 쿼리 드디어 내가 품!
https://school.programmers.co.kr/learn/courses/30/lessons/77487
SELECT ID,NAME,HOST_ID
FROM PLACES
WHERE HOST_ID IN
(
SELECT HOST_ID
FROM PLACES
GROUP BY HOST_ID
HAVING COUNT(NAME) >= 2
);
EXISTS는 또 무엇인가.....참고 링크
SELECT * FROM PLACES P1
WHERE EXISTS (
SELECT 1 FROM PLACES P2
WHERE P1.HOST_ID = P2.HOST_ID
GROUP BY HOST_ID
HAVING COUNT(ID) >= 2
)
ORDER BY ID ASC;
LV.4 주문량이 많은 아이스크림들 조회하기 (정답률 : 70%) - 🌟🌟🌟🌟🌟 서브 쿼리
https://school.programmers.co.kr/learn/courses/30/lessons/133027
SELECT A.FLAVOR
FROM FIRST_HALF A JOIN
(
SELECT FLAVOR, SUM(TOTAL_ORDER) AS TOTAL_ORDER
FROM JULY GROUP BY FLAVOR
) B ON A.FLAVOR = B.FLAVOR
ORDER BY (A.TOTAL_ORDER + B.TOTAL_ORDER) DESC
LIMIT 3;
ORDER BY에도 SUM함수랑 더하기 연산자 가능!!
SELECT A.FLAVOR
FROM FIRST_HALF A JOIN JULY B
ON A.FLAVOR = B.FLAVOR
GROUP BY A.FLAVOR
ORDER BY SUM(A.TOTAL_ORDER) + SUM(B.TOTAL_ORDER) DESC LIMIT 3;
LV.3 조회수가 가장 많은 중고거래 게시판의 첨부파일 조회하기 (정답률 : 68%) - 🌟🌟🌟 🌟 🌟 서브 쿼리 내가 품!
https://school.programmers.co.kr/learn/courses/30/lessons/164671
## 내가 푼 풀이
SELECT CONCAT('/home/grep/src/',F.BOARD_ID,'/',FILE_ID,FILE_NAME,FILE_EXT) AS FILE_PATH
FROM USED_GOODS_FILE F JOIN
(
SELECT BOARD_ID
FROM USED_GOODS_BOARD
GROUP BY BOARD_ID
ORDER BY VIEWS DESC LIMIT 1
) B ON F.BOARD_ID = B.BOARD_ID
ORDER BY FILE_ID DESC;
SELECT
CONCAT('/home/grep/src/', FILE.BOARD_ID, '/', FILE_ID, FILE_NAME, FILE_EXT) AS FILE_PATH
FROM USED_GOODS_FILE AS FILE
LEFT JOIN USED_GOODS_BOARD AS BOARD
ON FILE.BOARD_ID = BOARD.BOARD_ID
WHERE VIEWS = (SELECT MAX(VIEWS) FROM USED_GOODS_BOARD)
ORDER BY FILE_ID DESC
LV.4 저자 별 카테고리별 매출액 집계하기 (정답률 : 68%) - 🌟🌟🌟 🌟 🌟 서브 쿼리 내가 품!
https://school.programmers.co.kr/learn/courses/30/lessons/144856
이번에는 join절 안에 서브쿼리까지 잘 풀어놓고 SUM()을 안해서 계속 원하는 값이 안나왔다.
나는 왜 자꾸 SUM()을 안해주는 것인가?!?! 집계액이라고 나오면 SUM()꼭해라
-- 내가 푼 풀이
SELECT A.AUTHOR_ID, A.AUTHOR_NAME, B.CATEGORY, SUM(B.PRICE * S.SALES) AS TOTAL_SALES
FROM BOOK B
JOIN AUTHOR A ON B.AUTHOR_ID = A.AUTHOR_ID
JOIN
(
SELECT BOOK_ID, SUM(SALES) AS SALES
FROM BOOK_SALES
WHERE SALES_DATE LIKE '2022-01%'
GROUP BY BOOK_ID
) S ON B.BOOK_ID = S.BOOK_ID
GROUP BY A.AUTHOR_ID, B.CATEGORY
ORDER BY AUTHOR_ID, CATEGORY DESC;
SELECT A.AUTHOR_ID, AUTHOR_NAME, CATEGORY, SUM((SALES * PRICE)) AS TOTAL_SALES
FROM BOOK_SALES S
JOIN BOOK B ON S.BOOK_ID = B.BOOK_ID
JOIN AUTHOR A ON B.AUTHOR_ID = A.AUTHOR_ID
WHERE YEAR(S.SALES_DATE) = 2022 AND MONTH(S.SALES_DATE) = 1
GROUP BY CATEGORY, AUTHOR_ID
ORDER BY A.AUTHOR_ID, CATEGORY DESC
(궁금증, 테이블 전부다 조인하는거랑, 일부를 서브쿼리로 만들어서 조인하는거랑 성능차이가 있을까?)
LV.3 대여 횟수가 많은 자동차들의 월별 대여 횟수 구하기 (정답률 : 67%) - 🌟🌟🌟 🌟 🌟 서브 쿼리 내가 품!
https://school.programmers.co.kr/learn/courses/30/lessons/151139
해당 문제를 풀때 문제가 2가지였다
1. 서브쿼리를 만들고 붙였는데, 2번 id값이 7번이어야 하는데 계속 5번으로 나왔다 : 서브쿼리 내에 HAVING절을 추가안했다 나는 계쏙 이걸 바깥 쿼리에다가 넣으려고 했다
2. 서브쿼리에도 날짜 관련 WHERE절이 있고 , 메인쿼리에도 있는데 나는 메인쿼리에는 날짜 관련 WHERE절을 쓰지 않았었다 그래서 계속 실패햇는데, 무슨차이인지 모르겠다... 이미 서브쿼리에서 필터링을 한건데 왜 메인쿼리에서 또 해야하는가?
-- 내가 푼 풀이
SELECT MONTH(START_DATE) AS MONTH, CAR_ID, COUNT(*) AS RECORDS
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
WHERE START_DATE BETWEEN '2022-08-01' AND '2022-10-31'
AND (CAR_ID) IN
(
SELECT CAR_ID
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
WHERE START_DATE BETWEEN '2022-08-01' AND '2022-10-31'
GROUP BY CAR_ID
HAVING COUNT(CAR_ID) >= 5
)
GROUP BY CAR_ID, MONTH(START_DATE)
ORDER BY MONTH, CAR_ID DESC
-- 다른사람 풀이 START_DATE에 DATE_FORMAT적용
SELECT MONTH(START_DATE) AS MONTH, CAR_ID, COUNT(*) AS RECORDS
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
WHERE DATE_FORMAT(START_DATE, '%Y-%m') BETWEEN '2022-08' AND '2022-10'
AND (CAR_ID) IN
(
SELECT CAR_ID
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
WHERE DATE_FORMAT(START_DATE, '%Y-%m') BETWEEN '2022-08' AND '2022-10'
GROUP BY CAR_ID
HAVING COUNT(CAR_ID) >= 5
)
GROUP BY CAR_ID, MONTH(START_DATE)
HAVING RECORDS >= 1
ORDER BY MONTH, CAR_ID DESC
LV.4 그룹별 조건에 맞는 식당 목록 출력하기 (정답률 : 62%) - 🌟🌟🌟 🌟 🌟 서브 쿼리 내가 품!
https://school.programmers.co.kr/learn/courses/30/lessons/131124
문제를 제대로 읽지 않아서 리뷰를 가장 많이 작성한 사람 1명만 나온다는 의미를 몰랐다
그래서 LIMIT1을 안써서 계속 틀렸는데, 마지막에 수정했다.
-- 내가 푼 풀이
SELECT M.MEMBER_NAME, R.REVIEW_TEXT, DATE_FORMAT(R.REVIEW_DATE, '%Y-%m-%d') AS REVIEW_DATE
FROM MEMBER_PROFILE M JOIN REST_REVIEW R
ON M.MEMBER_ID = R.MEMBER_ID
WHERE M.MEMBER_ID =
(
SELECT MEMBER_ID
FROM REST_REVIEW
GROUP BY MEMBER_ID
ORDER BY COUNT(*) DESC LIMIT 1
)
ORDER BY R.REVIEW_DATE, R.REVIEW_TEXT
'Database > 프로그래머스' 카테고리의 다른 글
프로그래머스 SQL 76문제 풀기 ( 정답률 높은 순 기준 6개 ) - 5 (1) | 2023.10.06 |
---|---|
프로그래머스 SQL 76문제 풀기 ( 정답률 높은 순 기준 20개 ) - 3 (1) | 2023.10.04 |
프로그래머스 SQL 76문제 풀기 ( 정답률 높은 순 기준 10개 ) - 2 (0) | 2023.09.30 |
프로그래머스 SQL 76문제 풀기 ( 정답률 높은 순 기준 20개 ) - 1 (0) | 2023.09.29 |