WIL(24년 7월 3주)

Gi Woon Lee·2024년 7월 22일
0

TIL

목록 보기
21/78

SQL

70번. 그룹별 조건에 맞는 식당 목록 출력하기

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문 사용. 언젠가는 알아야 할 개념을 이악물고 외면하다가 처음 사용해봤다. 막상 써보니 별 거 아니라서 시시했다. 틀린 이유를 복습하면서 자세히 복기하자.

71번. 오프라인/온라인 판매 데이터 통합하기

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테이블의 이 모든 행에 채워진다.

72번. 조건에 맞는 중고거래 댓글 조회

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

73번. 입양 시각 구하기(2)(재귀CTE)

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

74번. 특정 기간동안 대여 가능한 자동차 대여비용 구하기

  • 나의 오답
SELECT -- 자동차 ID, 자동차 종류, 대여 금액(컬럼명: FEE) 출력
      C.CAR_ID
    , C.CAR_TYPE
    -- FEE: (대여 날짜 * 하루 대여비) * 할인적용률 -> 소수점 반올림(.00 제거)
    , CASE WHEN DATEDIFF(H.END_DATE,H.START_DATE)+1 >= 30 
           THEN ROUND(C.DAILY_FEE * (DATEDIFF(H.END_DATE,H.START_DATE)+1) * 0.93)
           WHEN DATEDIFF(H.END_DATE,H.START_DATE)+1 >= 7
           THEN ROUND(C.DAILY_FEE * (DATEDIFF(H.END_DATE,H.START_DATE)+1) * 0.95)
           ELSE C.DAILY_FEE * (DATEDIFF(H.END_DATE,H.START_DATE)+1)
           END FEE
FROM -- 3개 태이블 조인
    CAR_RENTAL_COMPANY_CAR C 
LEFT JOIN 
    CAR_RENTAL_COMPANY_RENTAL_HISTORY H ON C.CAR_ID = H.CAR_ID 
JOIN   
    CAR_RENTAL_COMPANY_DISCOUNT_PLAN P ON C.CAR_TYPE = P.CAR_TYPE
WHERE 
    P.CAR_TYPE IN ('세단','SUV') AND --  '세단' or 'SUV' 
    H.END_DATE < '2022-11-01' AND H.START_DATE < '2022-11-01' AND -- 2022-11-01 ~ 2022-11-30 대여 가능
    (C.DAILY_FEE * 30) - (C.DAILY_FEE * 30 * 0.1) >= 500000 AND -- 30일간의 대여 금액 >= 50만원
    (C.DAILY_FEE * 30) - (C.DAILY_FEE * 30 * 0.1) < 2000000     -- 30일간의 대여 금액 < 200만원
ORDER BY -- 대여 금액 DESC, 차 종류ASC, 자동차 ID DESC
    3 DESC, 2, 1 DESC
  1. JOIN 시 디폴트는 INNER JOIN이다. 위 사례에서 첫 번째 조인은 CAR_RENTAL_COMPANY_CAR 'LEFT JOIN'CAR_RENTAL_COMPANY_RENTAL_HISTORY 'ON' 을 했어야 했다.
    그래야 한번도 렌탈되지 않았지만 렌탈 가능한 차량이 조회되기 때문이다.

  2. JOIN - AND 로 WHERE절 필터링을 상당수 대체할 수 있다.


  • 박현경 튜터의 정답 쿼리
select
    a.car_id, 
    a.car_type,
    round(a.daily_fee*30*((100-b.discount_rate)/100)) as fee
    # c.*
from CAR_RENTAL_COMPANY_CAR as a 
inner join CAR_RENTAL_COMPANY_DISCOUNT_PLAN as b 
on a.car_type = b.car_type and a.car_type IN ('세단', 'SUV') and b.duration_type = '30일 이상'
left join CAR_RENTAL_COMPANY_RENTAL_HISTORY as c
on a.car_id = c.car_id and c.end_date > '2022-11-01'# and c.car_id is null
where c.history_id is null -- 2022년 11월 1일 이후에 대여 기록이 없는 자동차
having fee >= 500000 and fee < 2000000
order by 3 desc, 2, 1 desc
  1. 각 조인별로 해당되는 테이블에서 수행할 수 있는 필터링을 AND로 수행하였기에 정확도와 가독성이 높아진다.

  2. LEFT JOIN 으로 발생한 NULL값을 필터링에 사용하셨다.

75번. 자동차 대여 기록 별 대여 금액 구하기

이틀간 풀었다..

WITH TRUCK AS(
SELECT H.*, 
       C.DAILY_FEE,
       DATEDIFF(END_DATE, START_DATE) + 1 DURATION,
       CASE WHEN DATEDIFF(END_DATE, START_DATE) + 1 >= 90 THEN '90일 이상'
            WHEN DATEDIFF(END_DATE, START_DATE) + 1 >= 30 THEN '30일 이상'
            WHEN DATEDIFF(END_DATE, START_DATE) + 1 >= 7 THEN '7일 이상'
            ELSE '해당 없음' END  duration_type     # 할인하지 않는 경우를 꼭 기억해라. 이것때문에 30분 더 걸림. 
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY H JOIN CAR_RENTAL_COMPANY_CAR C
ON H.CAR_ID = C.CAR_ID AND C.CAR_TYPE = '트럭'    # CAR TABLE '트럭' 필터링
), TRUCK2 AS(
SELECT 
    HISTORY_ID,
    CASE WHEN T.DURATION_TYPE = '해당 없음' THEN DAILY_FEE * DURATION 
         WHEN T.DURATION_TYPE IN ('7일 이상','30일 이상','90일 이상') THEN DAILY_FEE * DURATION * (1-discount_rate/100)
         ELSE 0 END FEE
FROM TRUCK T LEFT JOIN CAR_RENTAL_COMPANY_DISCOUNT_PLAN P
ON T.DURATION_TYPE = P.DURATION_TYPE AND P.CAR_TYPE = '트럭'  # PLAN TABLE '트럭' 필터링
ORDER BY 2 DESC, 1 DESC)

SELECT HISTORY_ID, ROUND(FEE) # ROUNDING을 위한... MULTI CTE 활용
FROM TRUCK2

조건이 많은 문제를 풀 때는 "조건에 해당하지 않는 값" 을 어떻게 처리해야 하는지를 생각하고 쿼리를 작성하자.

위 문제의 경우 할인을 받지 않는 7일 미만의 대여 데이터가 절대 다수였는데 해당 경우를 쿼리에 포함하지 않아 정답 테이블 데이터의 거의 70퍼센트를 날려버릴뻔 했다.

실제 현업 데이터였으면 시말서 감이다. 목적을 분명하게 세운 뒤에 분석하자.

76번. 상품 구매 회원 비율 구하기

  • 나의 정답(이지만 뭔가 비효율적인) 쿼리
WITH 
SUM_2021 AS(
SELECT COUNT(DISTINCT(USER_ID))
FROM USER_INFO                     # 2021년 가입한 전체 회원 수
WHERE SUBSTR(JOINED,1,4) = '2021') # 158명
,
SUM_PURCHASED_2021 AS(
SELECT COUNT(DISTINCT(S.USER_ID))
FROM ONLINE_SALE S JOIN USER_INFO U
ON S.USER_ID = U.USER_ID             # 2021년 가입 회원 중 구매한 회원 수
WHERE SUBSTR(U.JOINED,1,4) = '2021') # 83명

SELECT 
    YEAR(S.SALES_DATE) YEAR
    , MONTH(S.SALES_DATE) MONTH
    , COUNT(DISTINCT(S.USER_ID)) PURCHASED_USERS
    , ROUND(COUNT(DISTINCT(S.USER_ID))/(SELECT * FROM SUM_2021),1) PUCHASED_RATIO # 비율 구하기
FROM ONLINE_SALE S JOIN USER_INFO U
ON S.USER_ID = U.USER_ID
WHERE SUBSTR(U.JOINED,1,4) = '2021'
GROUP BY 
    YEAR(S.SALES_DATE),
    MONTH(S.SALES_DATE)
ORDER BY 1, 2

비율을 구하는 과정이 복잡하여 with로 각 변수(2021 가입 회원 수, 2021 가입 회원 중 구매 회원 수) 를 각각 구해놓고 시작했다.

한 눈에 보기에도 비효율적이다...

  • 다른 사람의 효율적 쿼리
WITH JOIN_2021 AS(
SELECT COUNT(*) USERS FROM USER_INFO
WHERE YEAR(JOINED) = 2021)
,
PUCHASED_2021 AS(
SELECT 
	YEAR(SALES_DATE) AS YEAR, 
    MONTH(SALES_DATE) AS MONTH, 
    COUNT(DISTINCT(A.USER_ID)) AS PUCHASED_USERS 
FROM ONLINE_SALE A JOIN (
    SELECT USER_ID
    FROM USER_INFO
    WHERE YEAR(JOINED) = 2021) B
ON A.USER_ID = B.USER_ID
GROUP BY YEAR, MONTH)

SELECT P.YEAR, P.MONTH, P.PUCHASED_USERS, ROUND(P.PUCHASED_USERS/J.USERS,1) AS PUCHASED_RATIO
FROM PUCHASED P, JOIN_2021 J
ORDER BY YEAR, MONTH

Python

27번 핸드폰 번호 가리기

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:]

나도 개념들이 머리에 자리잡혀 이렇게 간단하게 코드를 짤 수 있기를..

28번 없는 숫자 더하기

  • 내가 작성한 오답..진심 답없음 ㅋㅋ
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

말 그대로 직관적이며 이해가 쉽지만 변수가 많아 효율적이진 않은 것 같다.


  • for 반복문을 통한 정답
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

머리가 좋으면 손가락이 편하다.

29번. 제일 작은 수 제거하기

  • 나의 오답
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

30번. 가운데 글자 가져오기

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[이상,미만,구간]을 잘 생각해서 비슷한 문제가 나오면 적극 활용하자.

  • 여기서는 왜 answer = 0 초기화를 안해도 되는가?
    answer: 조건문if-else에 의해 항상 answer값이 할당되기 때문이다.

31번. 수박수박수박수박수박수?

  • 나의 정답
def solution(n):
    if n % 2 == 0:
        answer = '수박'*(n//2)
    else:
        answer = '수박'*(n//2) + '수'
    return answer

32번.내적

zip() 함수를 사용하는 문제

def solution(a, b):
    answer = 0                  # answer 변수 초기화, 반복해서 더해줘야 하니까. 
    for x, y in zip(a, b):      # for i in x: x에서 i를 하나씩 뽑아서 반복
        answer = answer + x*y   # 반복해서 더해줌 
    return answer               # zip(a,b) 가 key point

아직까지도 for반복문을 바로 사용하지 못한다..
이래서 나중에 크롤링은 어떻게 할 것이며 머신러닝은 어떻게 돌릴거냐?
오늘 순공시간 3시간.. 반성하고 내일은 순공시간을 6시간 이상으로 가져가자.

그래도 zip()함수 하나를 알고 넘어가는 오늘이다.

  • zip(iterator1, iterator2, iterator3 ...)
    각 iterator의 상응하는 요소들끼리 묶어준다.
    이 때 짝이 만들어지지 않으면 해당 요소는 제외한다.

33번. 약수의 개수와 덧셈

  • 나의 오답... 좋은 시도
def solution(left, right):
    measure = []
    for x in range(left, right+1):
        for i in range(1, x+1):  
            if x % i == 0:              # 약수 찾기
                measure.append(i)
        if len(measure) % 2 == 0:       # 약수 개수 점검
            return x
        else:
            return -x

약수 리스트 measure를 만들어 담아낸 후, 해당 약수의 짝/홀 여부를 필터링하다가 실패했다.

feedback
1. 약수의 개수:
measure리스트는 매 반복마다 초기화되지 않아 약수가 계속 누적됨
2. return 위치:
return문이 for 루프 안에 있어서 첫 번째 결과를 계산한 뒤 바로 함수가 종료된다. 즉 누적된 결과를 계산하지 못한다.


  • 정답 코드
def count_division(n):  # 약수 개수
    count = 0
    for i in range(1, n+1): # range(n)은 '0' ~ 'n-1' 까지의 숫자를 생성. i로 나눌 시 ZeroDivisionError 발생, 시작 범위를 정해줘야함. 
        if n % i == 0:      # i 를 계속 1로 써서 모든 경우를 count+1 해버렸다..
            count += 1
    return count

def solution(left, right):
    result = 0   # 자꾸 sum 쓰려고 하는데, for문에서는 sum 말고 변수 선언과 += 를 통해 iteration 별 sum을 수행하라.  
    for x in range(left, right+1):
        if count_division(x) % 2 == 0:  # 짝수면
            result += x
        else:                           # 홀수면
            result -= x
    return result
  1. 약수의 개수를 구하는 함수를 따로 정의하여 편리하게 사용했다.
    sql에서 cte의 역할을 하는 def 함수를 적극 활용하자.

  2. ZeroDivisionError 를 주의하자. range(n)은 '0' ~ 'n-1' 까지의 숫자를 생성한다. 따라서 나눗셈의 경우 시작을 명시해줌으로써 ZeroDivisionError를 피해야 할 것이다.

  3. 반복문을 통한 누적 덧셈이 필요할 땐, sum 이 아니라 변수선언과 =+를 통한 iteration별 합계를 사용해야 한다.


  • 멋진 답 (제곱근을 사용한 약수 개수의 홀-짝 여부 확인하기)
def solution(left, right):
    answer = 0
    for i in range(left,right+1):
        if int(i**0.5)==i**0.5:     # 제곱수인지 확인! 
            answer -= i
        else:
            answer += i
    return answer

int(i**0.5) == i**0.5 는 'i'가 제곱수인지 아닌지 확인한다.

"제곱수는 약수 커플 중 쌍둥이를 갖는다."
일반적으로 숫자 n의 약수는 쌍을 이룬다.
ex)
36의 약수: (1, 36), (2, 18), (3, 12), (4, 9), (6, 6)
-> 쌍둥이 커플(6, 6)을 갖고 개수는 홀수이다.
20의 약수: (1, 20), (2, 10), (4, 5)
-> 약수들이 서로 다른 쌍을 이루며 개수는 짝수이다.

34번. 문자열 내림차순 정렬

def solution(s):
    answer = "".join(sorted(s, reverse=True))
    return answer
    
# s: "Zbcdefg"
# 결과: "gfedcbZ"

문자열 매서드 join()과 sorted함수를 적절히 사용하였다.

sort와 sorted의 차이가 헷갈렸다.

이 문제에서는 input값이 str 이라서 sorted()함수를 사용했다.

sort VS sorted
sort: 리스트 객체 메서드. 리스트를 직접 수정.
sorted: 일반 함수. literable 객체(튜플, 문자열..)에 사용 가능. 정렬된 리스트를 반환.

35번. 부족한 금액 계산하기

  • 나의 오답
def solution(price, money, count):
    fee = 0
    for i in range(1, count + 1):
        fee = fee + (price * i)
    return abs(money-fee)

다 잘 해놓고 문제 마지막 줄 "단, 금액이 부족하지 않으면 0을 return 하세요."를 안읽어서 오래걸렸다.

문제 똑바로 읽어라


  • 정답
def solution(price, money, count):
    fee = 0
    for i in range(1, count + 1):
        fee = fee + (price * i)
    if money-fee > 0:
        return 0
    else:
        return abs(money-fee)

절댓값 abs()가 사용된 문제였다.

36번. 문자열 다루기 기본

  • 나의 오답
def solution(s):
    if (len(s) == 4 or 6) and s.isdigit(): 
        return True
    else:
        return False

...틀린이유
1. 컴퓨터 이해 능력 이슈:
len(s) = 4 or 6 을 컴퓨터는 4 or True 로 인식한다.
컴퓨터는 0 아니면 전부 True로 해석하며 병렬정 이해를 하지 못한다.
또한 ==or보다 연산 속도가 빠르다.


  • 정답 by 임정 튜터
def solution(s):
    if len(s) == 4 or len(s) == 6:
        return s.isdigit()
    else:
        return False # 반드시 명시 필요

오답 원인을 제거하고 len(s) == 6을 명시했다.

또한 len(s) == 5인 경우 True로 해석하기 때문에 return s.isdigit()에서 끝내면 안되고 else조건을 걸어 false조건을 명시해줘야 한다.


  • 팀원의 정답
def solution(s):
    return s.isdigit() if len(s) == 4 or len(s) == 6 else false 

: 삼항 연산자를 사용하여 간단하게 풀었다.


  • 멋진 정답
def alpha_string46(s):
    # 함수가 주어진 문자열 s가 숫자로만 이루어져 있는지와 길이가 4 또는 6인지 확인합니다.
    return s.isdigit() and len(s) in [4, 6]

# 테스트 코드
print(alpha_string46("a234"))  # False
print(alpha_string46("1234"))  # True

and로 두 개의 조건을 연결하고, in 연산자를 통해 문자열의 길이 조건 명시했다.
논리연산자만을 사용한 깔끔한 코드.

37번. 행렬의 덧셈

def solution(arr1, arr2):
    answer = []
    
    for i in range(len(arr1)):  # 행의 합
        arr_sum = []
        for j in range(len(arr1[0])):   # 열의 합
            arr_sum.append(arr1[i][j] + arr2[i][j])
        answer.append(arr_sum)
    
    return answer

개념

CTE (일반CTE, 재귀CTE)

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;

[SQL] CTE (일반CTE, 재귀CTE)

일반CTE Syntax

: 하위 쿼리를 정의하고 참조하는 방법

WITH cte_name AS (
    SELECT column1, column2, ...
    FROM table_name
    WHERE condition
)
SELECT column1, column2, ...
FROM cte_name;

재귀CTE syntax

: 자기 자신을 반복적으로 호출하여 계층적/반복적 데이터를 처리한다. 엥커, 재귀로 구성됨.

  • UNION ALL
    : UNION ALL은 모든 결과 행을 포함하는 반면 UNION은 중복된 행을 제거한다. RECURSIVE CTE에서는 보통 의도적으로 중복된 행을 포함하기에 UNION ALL을 사용한다.
WITH RECURSIVE cte_name AS (
    -- 앵커 멤버
    SELECT initial_query
    UNION ALL
    -- 재귀 멤버
    SELECT recursive_query
    FROM cte_name
    WHERE termination_condition
)
SELECT * FROM cte_name;

0 ~ 10 숫자를 생성하는 재귀CTE 예제

WITH RECURSIVE Numbers AS (
    -- 앵커 멤버: 0을 반환
    SELECT 0 AS number
    UNION ALL
    -- 재귀 멤버: number에 1을 더해가면서 10 이하일 때까지 반복
    SELECT number + 1
    FROM Numbers
    WHERE number < 10
)
SELECT number FROM Numbers;

[Python] zip()

  • zip(iterator1, iterator2, iterator3 ...)
    각 iterator의 상응하는 요소들끼리 묶어준다.
    이 때 짝이 만들어지지 않으면 해당 요소는 제외한다.
a = ("John", "Charles", "Mike")
b = ("Jenny", "Christy", "Monica", "Vicky")

x = zip(a, b)

#use the tuple() function to display a readable version of the result:

print(tuple(x))

# 결과: (('John', 'Jenny'), ('Charles', 'Christy'), ('Mike', 'Monica'))

[Python] sort(), sorted() method

sort(): 리스트 객체 메서드, 기존 객체를 정렬
sorted(): iterable 객체(튜플, 문자열 등) 메서드, 정렬된 new 리스트를 반환하며 기존 객체는 변하지 않음

sort, sorted 비교 예시

# sort() 예시
numbers = [3, 1, 4, 1, 5, 9]
numbers.sort()
print(numbers)  # 출력: [1, 1, 3, 4, 5, 9]
---
# sorted() 예시
numbers = [3, 1, 4, 1, 5, 9]
sorted_numbers = sorted(numbers)
print(numbers)  # 출력: [3, 1, 4, 1, 5, 9]
print(sorted_numbers)  # 출력: [1, 1, 3, 4, 5, 9]
  • syntax
    numbers.sort(reverse, key)
    reverse: 오름차순:reverse=False 디폴트. 내림차순:reverse=True
    key: 정렬 기준을 정하는 함수. ex) len, lambda...

[Python] 함수와 매서드의 차이

  • 메서드 (Method): 객체를 대상으로 종속적으로 작동. 점 표기
    object.method_name()

  • 함수 (Function): 어디서든 독립적으로 작동하는 코드. 괄효 표기
    function()

Functions are independent blocks of code that can be called from anywhere, while methods are tied to objects or classes and need an object or class instance to be invoked

[Python] 삼항연산자

삼항 연산자(ternary operator):
syntax -> True 값 if 조건 else False 값

삼항연산자 활용 예시
ex-1)

# 홀/짝 판별
number = 5
result = "Even" if number % 2 == 0 else "Odd"
print(result)  # 출력: Odd

ex-2)

age = 18
message = "Adult" if age >= 18 else "Minor"
print(message)  # 출력: Adult

코딩 팁

직접 쓰면서 해봐라.
work flow를 그리면서 하면 훨씬 괜찮다.

0개의 댓글