WITH MOST AS (
SELECT MEMBER_ID, COUNT(*) AS CNT
FROM REST_REVIEW
GROUP BY MEMBER_ID
ORDER BY CNT DESC
LIMIT 1
)
SELECT P.MEMBER_NAME,
R.REVIEW_TEXT,
DATE_FORMAT(R.REVIEW_DATE, '%Y-%m-%d') AS REVIEW_DATE
FROM MEMBER_PROFILE P
JOIN REST_REVIEW R ON P.MEMBER_ID = R.MEMBER_ID
JOIN MOST M ON R.MEMBER_ID = M.MEMBER_ID
ORDER BY R.REVIEW_DATE ASC, R.REVIEW_TEXT ASC;
#틀린 이유 1. WITH 절 SELECT문에서 GROUP BY로 집계하지 않는 REVIEW_TEXT를 반환시켰다.
# 2. LIMIT 1이 아닌 LIMIT 3을 사용했다.
# 3. 문제를 잘 안읽고 ASC를 DESC로 작성했다.
# 4. GROUP BY를 사용한 집계함수 결과에 대한 필터링은 HAVING을 사용해야만 한다.
첫 with문 사용. 언젠가는 알아야 할 개념을 이악물고 외면하다가 처음 사용해봤다. 막상 써보니 별 거 아니라서 시시했다. 틀린 이유를 복습하면서 자세히 복기하자.
SELECT DATE_FORMAT(SALES_DATE, '%Y-%m-%d')SALES_DATE,
PRODUCT_ID, USER_ID, SALES_AMOUNT
FROM
(SELECT SALES_DATE, PRODUCT_ID, USER_ID, SALES_AMOUNT
FROM ONLINE_SALE
WHERE SALES_DATE LIKE '2022-03%'
UNION
SELECT SALES_DATE, PRODUCT_ID, NULL, SALES_AMOUNT
FROM OFFLINE_SALE
WHERE SALES_DATE LIKE '2022-03%') A
ORDER BY 1,2,3
UNION을 처음 사용한 쿼리.
JOIN: 관계가 있어야 한다. 두 테이블에 각각 존재하는 '다른 의미를 가지는' 날짜 데이터끼리 JOIN을 해 봐야 의미가 없다. '같은 내용의 행 데이터를 같는 횡결합
UNION: 독립된 두 테이블이지만 '동일한 형식의 열 칼럼'을 갖는 종결합
이 때, 1 UNION 2 테이블에서 2테이블의 칼럼이 하나 없더라도, SELECT 칼럼 자리에 값을 넣으면 1테이블 칼럼명을 그대로 쓰되 2테이블의 값이 모든 행에 채워진다.
SELECT B.TITLE, B.BOARD_ID, R.REPLY_ID, R.WRITER_ID, R.CONTENTS,
DATE_FORMAT(R.CREATED_DATE, '%Y-%m-%d') CREATED_DATE
FROM USED_GOODS_REPLY R JOIN USED_GOODS_BOARD B
ON R.BOARD_ID = B.BOARD_ID
WHERE B.CREATED_DATE LIKE '2022-10%'
ORDER BY R.CREATED_DATE, B.TITLE
WITH RECURSIVE CREATED_HOURS AS ( # 'WITH RECURSIVE' 까지가 재귀CTE 선언 함수
-- 앵커 멤버: 0을 반환
SELECT 0 AS HOUR
UNION ALL
-- 재귀 멤버: number에 1을 더해가면서 24 이하까지
SELECT HOUR + 1
FROM CREATED_HOURS
WHERE HOUR < 23 # SELECT에서 + 1 이 있으니까 23까지 반환한다.
)
SELECT C.HOUR,
CASE WHEN COUNT IS NULL THEN '0' # NULL 값에 '0' 을 넣어주고
ELSE COUNT END COUNT # 나머지 값은 그대로 소환
FROM CREATED_HOURS C
LEFT JOIN # 재귀CTE로 생성한 0~23 숫자를 모두 살려야 하기에 LEFT JOIN
(SELECT HOUR(DATETIME) HOUR, COUNT(ANIMAL_ID) COUNT
FROM ANIMAL_OUTS
GROUP BY HOUR(DATETIME)) A
ON C.HOUR = A.HOUR
def solution(phone_number):
length = len(phone_number) - 4 # 길이 변수 생성
masking_part = '*' * length # 마스킹 파트 변수 생성
last_four_digits = phone_number[-4:] # 뒤 4자리 변수 생성
masked_number = masking_part + last_four_digits # 마스킹 파트 + 뒤 4자리를 통해 마스킹 완료된 값 반환
return masked_number
indexing, 문자열 사칙연산 같은 마법카드를 몇 장 사용하면 다음과 같은 최적화 코드가 나온다.
def hide_numbers(phone_number):
return ('*'*(len(phone_number)-4)) + phone_number[-4:]
나도 개념들이 머리에 자리잡혀 이렇게 간단하게 코드를 짤 수 있기를..
def solution(numbers):
for num in numbers: # 이러면 안돼...문제에 1~10에 없는 값을 number 로 준다고 하잖아.
if num != range(1:10): # range함수 구조: range(시작,미만값,구간) 이다
answer = print(sum(num)) # sum함수는 literable 객체에만 사용 가능하다.
return answer
총체적 난국인 나의 코드를 하나씩 짚어보자.
1. 우선 sum()함수는 literable 객체에만 사용이 가능하다.
2. range() 의 구조는 range(시작값, 미만값, 구간) 이다. ' : '은 대체 어디서 온 걸까.
3. 멤버십 검증을 위해 멤버십 연산자 in or not in 을 사용해야 한다. =, !=은 비교 연산자로 두 값을 비교하는 역할이다.
def solution(numbers):
total_number = sum(range(10))
given_number = sum(numbers)
answer = total_number - given_number
return answer
말 그대로 직관적이며 이해가 쉽지만 변수가 많아 효율적이진 않은 것 같다.
def solution(numbers):
answer = 0
for i in range(1,10):
if i not in numbers:
answer += i
return answer
가장 흔하게 쓰이는 구조이다. 이 구조를 디폴트로 생각할 줄 알아야겠다.
answer = 0 변수 초기화, range()를 통한 구간 생성, 멤버십 연산자 등의 개념을 기억하자.
def solution(numbers):
answer = sum(range(10)) - sum(numbers)
return answer
머리가 좋으면 손가락이 편하다.
def solution(arr):
min_value = min(arr)
answer = arr.remove(min_value) # .remove() 메서드는 arr 리스트를 직접 수정하기 때문에 answer에 아무것도 반환하지 않는다.
if len(arr) < 2:
return [-1]
else:
return answer
내가 answer 변수에 remove()메서드로 최소값을 제거한 arr리스트를 담으려고 한 것에서 오류가 발생했다.
리스트 내 값을 삭제하는 .remove(값)메서드는 리스트를 직접 수정하기 때문에 아무것도 반환하지 않느다.
따라서 .remove()메서드의 결과를 저장하는 answer 또한 null값을 가지게 된다.
def solution(arr):
min_value = min(arr)
arr.remove(min_value)
if len(arr) < 2:
return [-1]
else:
return arr
def solution(s):
answer = 0
if len(s) % 2 != 0:
answer = s[len(s)//2]
else:
answer = s[len(s)//2-1:len(s)//2+1]
return answer
indexing 문제다. 짝수와 홀수의 경우로 나눈 뒤 인덱스 범위를 사용할 수 있는지 확인하는 문제였음. list[이상,미만,구간]을 잘 생각해서 비슷한 문제가 나오면 적극 활용하자.
def solution(n):
if n % 2 == 0:
answer = '수박'*(n//2)
else:
answer = '수박'*(n//2) + '수'
return answer
WITH
cte1 AS (SELECT a, b FROM table1),
cte2 AS (SELECT c, d FROM table2)
SELECT b, d FROM cte1 JOIN cte2
WHERE cte1.a = cte2.c;