TIL

4주차 월요일

whateveryouwish 2024. 7. 22. 18:51

SQL

 

 

36번

보호소에서 중성화 수술을 거친 동물 정보를 알아보려 합니다.
보호소에 들어올 당시에는 중성화1되지 않았지만,
보호소를 나갈 당시에는 중성화된 동물의 아이디와 생물 종, 이름을 조회하는 아이디 순으로
조회하는 SQL 문을 작성해주세요.
SELECT i.animal_id, i.animal_type, i.name
from animal_ins i
inner join animal_outs o on i.animal_id = o.animal_id
where i.sex_upon_intake like 'intact%'
    and (o.sex_upon_outcome like 'spayed%'
    or o.sex_upon_outcome like 'neutered%')
order by i.animal_id

 

and 와 or 가 연결되어 있을 때 ()의 활용을 적절하게 이해하고 있어야 잘 풀리는 문제.

 

37번

 

문제
'경제' 카테고리에 속하는 도서들의
도서 ID(BOOK_ID), 저자명(AUTHOR_NAME), 출판일(PUBLISHED_DATE)
리스트를 출력하는 SQL문을 작성해주세요.
결과는 출판일을 기준으로 오름차순 정렬해주세요.

주의사항
PUBLISHED_DATE의 데이트 포맷이 예시와 동일해야 정답처리 됩니다.

 

SELECT book_id, author_name, date_format(published_date, '%Y-%m-%d')
from book b
inner join author a on b.author_id = a.author_id
where category like "경제"
order by published_date

 

inner join 용법과 where 절을 적절히 사용하면서

date_format 사용법을 알고있는지를 묻는 문제이다.

 

- DATE_FORMAT()

기본 문법: DATE_FORMAT(date, format)

사용 예시:
DATE_FORMAT(order_date, '%Y-%m-%d'): 주문 날짜를 'YYYY-MM-DD' 형식으로 출력
DATE_FORMAT(order_date, '%b %d, %Y'): 주문 날짜를 'MMM DD, YYYY' 형식으로 출력
DATE_FORMAT(order_date, '%H:%i:%s'): 주문 시간을 'HH:MM:SS' 형식으로 출력

지원되는 형식 문자열:
%Y: 4자리 연도
%y: 2자리 연도
%M: 월 이름(January, February, ...)
%b: 월 이름 약어(Jan, Feb, ...)
%m: 2자리 월(01, 02, ...)
%d: 2자리 일(01, 02, ...)
%e: 1자리 일(1, 2, ...)
%H: 24시간 형식의 시(00, 01, ...)
%h: 12시간 형식의 시(01, 02, ...)
%i: 2자리 분(00, 01, ...)
%s: 2자리 초(00, 01, ...)
%p: AM/PM 표시


- CONCAT()

기본 문법: CONCAT(str1, str2, ...)

사용 예시:
CONCAT(first_name, ' ', last_name): 이름과 성을 하나의 문자열로 연결
CONCAT(YEAR(order_date), '-', LPAD(MONTH(order_date), 2, '0'), '-', LPAD(DAY(order_date), 2, '0')): 주문 날짜를 'YYYY-MM-DD' 형식으로 출력
CONCAT(LPAD(HOUR(order_time), 2, '0'), ':', LPAD(MINUTE(order_time), 2, '0'), ':', LPAD(SECOND(order_time), 2, '0')): 주문 시간을 'HH:MM:SS' 형식으로 출력

추가 기능:
LPAD(str, len, padstr): 문자열 왼쪽에 지정된 문자열로 길이를 맞춤
RPAD(str, len, padstr): 문자열 오른쪽에 지정된 문자열로 길이를 맞춤
YEAR(date), MONTH(date), DAY(date), HOUR(time), MINUTE(time), SECOND(time): 날짜/시간 각 부분 추출

이러한 함수들을 조합하면 다양한 형식으로 날짜와 시간을 출력할 수 있습니다. 필요에 따라 적절한 함수와 형식 문자열을 선택하여 사용하면 됩니다.

 

38번

문제
FOOD_ORDER 테이블에서 2022년 5월 1일을 기준으로
주문 ID, 제품 ID, 출고일자, 출고여부를 조회하는 SQL문을 작성해주세요.
출고여부는 2022년 5월 1일까지 출고완료로 이 후 날짜는 출고 대기로 미정이면 출고미정으로 출력해주시고,
결과는 주문 ID를 기준으로 오름차순 정렬해주세요.
SELECT order_id, product_id, date_format(out_date, '%Y-%m-%d') as outdate,
    case
        when out_date <= '2022-05-01' then "출고완료"
        when out_date > '2022-05-01' then "출고대기"
        else "출고미정"
    end as "출고여부"
from food_order
order by order_id

 

case when 활용법을 물어보는 문제다. 중요한 건 들여쓰기이다.

date_format 또한 이전 문제와 더불어 같이 쓰였다.

 

out_date 값이 null 일 경우를 나머지로 쓰지 않고

WHEN out_date IS NULL THEN '출고미정'

 

으로 씀으로써 문제를 풀 수도 있다.

 

39번

 

문제
상반기 동안 각 아이스크림 성분 타입과 성분 타입에 대한 아이스크림의 총주문량을
총주문량이 작은 순서대로 조회하는 SQL 문을 작성해주세요.
이때 총주문량을 나타내는 컬럼명은 TOTAL_ORDER로 지정해주세요.
SELECT ingredient_type, sum(total_order)
from first_half f
inner join icecream_info i on f.flavor = i.flavor
group by ingredient_type
order by total_order

 

40번

 

동물 보호소에 들어온 동물 중
이름이 Lucy, Ella, Pickle, Rogan, Sabrina, Mitty인 동물의
아이디와 이름, 성별 및 중성화 여부를 조회하는 SQL 문을 작성해주세요.
이때 결과는 아이디 순으로 조회해주세요.
SELECT animal_id, name, sex_upon_intake
from animal_ins
where name in ('lucy', 'ella', 'pickle', 'rogan', 'sabrina', 'mitty')
order by animal_id

 

where 절에서 in 의 활용법을 묻는 문제이다.

like을 써도 풀리는 문제이지만 굉장히 쿼리가 길어진다.

IN 연산자

IN 연산자는 여러 값 중 하나와 일치하는 행을 선택할 때 사용합니다.
이는 여러 개의 OR 조건을 간단히 표현할 수 있게 해줍니다.

IN 연산자의 기본 구문은 다음과 같습니다

SELECT column1, column2, ...
FROM table_name
WHERE column IN (value1, value2, ..., valueN);

IN 연산자의 활용 방법은 다음과 같습니다:

1. 단일 열 비교:

SELECT * FROM users WHERE name IN ('John', 'Jane', 'Bob');

이 쿼리는 name 열이 'John', 'Jane', 'Bob' 중 하나인 행을 모두 선택합니다.

2. 다중 열 비교:

SELECT * FROM orders 
WHERE (product_id, order_date) IN ((1, '2022-01-01'),
(2, '2022-02-15'), (3, '2022-03-30'));

이 쿼리는 product_id와 order_date가 각각 (1, '2022-01-01'),
(2, '2022-02-15'), (3, '2022-03-30') 중 하나인 행을 모두 선택합니다.

3. 서브쿼리와 함께 사용:

SELECT * FROM products 
WHERE category_id IN (SELECT id FROM categories WHERE is_active = 1);

이 쿼리는 categories 테이블에서 is_active가 1인 행의 id 값을 가져와,
products 테이블의 category_id가 이 값 중 하나인 행을 모두 선택합니다.

IN 연산자는 OR 연산자보다 가독성이 좋고, 쿼리 실행 속도도 빠르기 때문에 많이 사용됩니다.
특히 여러 값을 비교해야 하는 경우에 유용합니다.

 

알고리즘

 

16번

 

문제 설명

함수 solution은 정수 x와 자연수 n을 입력 받아,
x부터 시작해 x씩 증가하는 숫자를 n개 지니는 리스트를 리턴해야 합니다.
다음 제한 조건을 보고, 조건을 만족하는 함수, solution을 완성해주세요.

제한 조건

x는 -10000000 이상, 10000000 이하인 정수입니다.
n은 1000 이하인 자연수입니다.

 

def solution(x, n):
    answer = []
    for i in range(n):
        i = x + x*i
        answer.append(i)
    return answer

 

17번

 

문제 설명

자연수 n을 뒤집어 각 자리 숫자를 원소로 가지는 배열 형태로 리턴해주세요.
예를들어 n이 12345이면 [5,4,3,2,1]을 리턴합니다.

제한 조건

n은 10,000,000,000이하인 자연수입니다.
def solution(n):
    answer = [int(digit) for digit in str(n)]
    reversed_answer = answer[::-1]
    return reversed_answer

 

13번 문제처럼 풀면 된다.

answer = [int(digit) for digit in str(n)] 부분을 풀어서 설명하자면

1. str(n): 정수 n을 문자열로 변환한다.

2. [int(digit) for digit in str(n)]: 이 부분은 리스트 컴프리헨션(List Comprehension)을 사용한 것이다.
	- for digit in str(n): str(n)의 각 문자(자릿수)를 순회한다.
	- int(digit): 각 문자를 정수로 변환한다.
	- 이 과정을 통해 n의 각 자릿수를 정수로 변환하여 리스트로 만든다.

예를 들어, n = 12345라면 다음과 같은 과정을 거쳐 결과를 얻는다:

str(n) => '12345'
[int(digit) for digit in str(n)] => [1, 2, 3, 4, 5]
이렇게 만들어진 리스트 digits에는 n의 각 자릿수가 정수로 저장된다.

 

또한 리스트를 역순으로 정렬하는 3가지 방법은 뤼튼을 통해 밑에 정리해두었다.

 

파이썬에서 리스트를 역순으로 변환하는 방법은 크게 3가지가 있습니다:

1. 슬라이싱 사용하기:

my_list = [1, 2, 3, 4, 5]
reversed_list = my_list[::-1]
print(reversed_list)  # [5, 4, 3, 2, 1]
슬라이싱 연산자 [::-1]을 사용하면 리스트를 역순으로 만들 수 있습니다.

2. 내장 함수 reversed() 사용하기:

my_list = [1, 2, 3, 4, 5]
reversed_list = list(reversed(my_list))
print(reversed_list)  # [5, 4, 3, 2, 1]
reversed(my_list)는 리스트의 역순 이터레이터를 반환하므로, list()로 감싸서 리스트로 변환해야 합니다.

3. 메서드 reverse() 사용하기:

my_list = [1, 2, 3, 4, 5]
my_list.reverse()
print(my_list)  # [5, 4, 3, 2, 1]
리스트의 reverse() 메서드를 사용하면 리스트 자체를 역순으로 변경합니다.

이 세 가지 방법 중 가장 간단한 것은 슬라이싱 연산자 [::-1]을 사용하는 것입니다.
하지만 reversed() 함수나 reverse() 메서드를 사용하면
원본 리스트를 직접 변경할 수 있어 메모리 사용을 줄일 수 있습니다.

 

18번

 

문제 설명

문자열 s를 숫자로 변환한 결과를 반환하는 함수, solution을 완성하세요.

제한 조건

s의 길이는 1 이상 5이하입니다.
s의 맨앞에는 부호(+, -)가 올 수 있습니다.
s는 부호와 숫자로만 이루어져있습니다.
s는 "0"으로 시작하지 않습니다.

입출력 예

예를들어 str이 "1234"이면 1234를 반환하고, "-1234"이면 -1234를 반환하면 됩니다.
str은 부호(+,-)와 숫자로만 구성되어 있고, 잘못된 값이 입력되는 경우는 없습니다.
def solution(s):
    return int(s)

 

이 문제는 풀려면 코드가 엄청 길게 나올 거 같아서

한 번만 힌트를 보자 하고 질문하기를 눌렀다가

기운님의 풀이를 보고 반가워서 가져왔다.

def solution(s):
    # 부호 처리
    sign = 1
    if s[0] == '-':
        sign = -1
        s = s[1:]
    elif s[0] == '+':
        s = s[1:]
    
    # 숫자 변환
    result = 0
    for char in s.split():
        result = result * 10 + int(char)
    
    return result * sign

 

시간이 너무 걸릴 것 같아 뤼튼에게 물어봤다.

 

#부호 처리

sign을 1로 지정해두고 만약 문자열의 첫번째가 '-'일 경우 이 sign을 -1로 지정하여

나중에 각 문자열을 정수로 변환할 때 부호를 지정해줄 수 있다.

이후 리스트에서 [0] 부분을 제거한 채로 다시 s에 지정한다.

 

#숫자 변환

s의 문자열을 split()을 통해 쪼개어 리스트에 반환하고

모든 문자열에 대해 순서대로 10씩 곱하여

정수로 변환했을 때 그 순서를 그대로 지킬 수 있게 만든 것이다.

 

예를 들어 s가 -234라면

#부호 처리 부분에서 sign이 -1로 지정된 후에 문자열 s가 len(s) = 3인 상태가 된다

 

#숫자 변환 부분에서 s의 문자열이 '2', '3', '4' 의 형태를 가진 리스트에서

for 문을 통해 순서대로

x = x * 10 + 2

x = 2 * 10 + 3

x = 23 * 10 + 4

result = x = 234 순으로 진행된다.

 

마지막에 sign * result 하면 끝

 

근데, 문제에서는 사실 문자열 s라고 했기 때문에

문자열 s = '12-45'이면 이렇게 풀릴 수 없지 않나? 싶어서

또 시간 끌리고 싶지 않아서 뤼튼에 가볍게 질문했는데

 

뤼튼 said

좋은 질문입니다. 문자열에 부호가 포함된 경우에도 해결할 수 있도록 코드를 수정해야 합니다.

 
def solution(s):
    # 부호 처리
    sign = 1
    if s[0] == '-':
        sign = -1
        s = s[1:]
    elif s[0] == '+':
        s = s[1:]
    
    # 숫자 변환
    result = 0
    for char in s.split('-'):
        temp = 0
        for num in char.split('+'):
            temp = temp * 10 + int(num)
        if char != s:
            result -= temp
        else:
            result += temp
    
    return result * sign

이 코드의 동작 방식은 다음과 같습니다:

  1. 문자열 s의 첫 번째 문자가 부호인 경우, 부호를 저장하고 문자열을 슬라이싱하여 부호를 제거합니다.
  2. split('-') 함수를 사용하여 문자열을 '-' 기준으로 분리합니다. 이는 음수 처리를 위해 필요합니다.
  3. 각 부분 문자열에 대해 split('+') 함수를 사용하여 숫자를 추출하고, 이를 정수로 변환하여 누적합니다.
  4. 만약 현재 부분 문자열이 원래 문자열 s와 다르다면(즉, 음수 부분), 누적합에서 해당 값을 뺍니다.
  5. 마지막으로 부호를 적용하여 최종 결과를 반환합니다.

이 방법은 문자열에 부호가 포함된 경우에도 올바르게 동작합니다. 예를 들어, 문자열 "12-34"는 12 - 34 = -22로 계산됩니다.

 

뤼튼이든 지피티든 너무 믿지 마세요...

이거 어려운 문제인듯..!?

 

레벨1이니 의도는 기운님이 푼 대로 하는 게 맞았나보다.

 

아무리 생각해도 실험을 좀 해보고 싶어서 collab으로 직접 문자열을 입력하게 만들고

12-45 를 문자열로 넣어봤다.

int()변환이 연산자 처리가 가능한지 궁금했다.

역시나 정수 변환은 변환만 해줄 뿐이고 코드를 실행하면 오류가 뜬다.

 

문제 오류 같은데..?

내 빼앗긴 시간 어쩔거야

 

19번

문제 설명

임의의 양의 정수 n에 대해, n이 어떤 양의 정수 x의 제곱인지 아닌지 판단하려 합니다.
n이 양의 정수 x의 제곱이라면 x+1의 제곱을 리턴하고,
n이 양의 정수 x의 제곱이 아니라면 -1을 리턴하는 함수를 완성하세요.

제한 사항

n은 1이상, 50000000000000 이하인 양의 정수입니다.
def solution(n):
    answer = 0
    for x in range(1, n+1):
        if n == x**2:
            answer = (x+1)**2
            break
        else:
            answer = -1
    return answer

 

 

break가 없으면 x가 계속 for 문을 돌면서 -1로 끝나게 되는 경우가 있다.

또한 연산 속도가 엄-청 느려진다.

break 사용 필수!

 

오늘의 마지막 코드카타

20번

문제 설명

함수 solution은 정수 n을 매개변수로 입력받습니다.
n의 각 자릿수를 큰것부터 작은 순으로 정렬한 새로운 정수를 리턴해주세요.
예를들어 n이 118372면 873211을 리턴하면 됩니다.

제한 조건

n은 1이상 8000000000 이하인 자연수입니다.

 

def solution(n):
    answer = 0
    digits = [int(digit) for digit in str(n)]
    sorted_digits = sorted(digits)
    my_list = sorted_digits.reverse()
    for i in sorted_digits:
        answer = answer * 10 + i
    return answer

 

오늘 푼 문제들 중 17번, 저번주 목요일에 푼 13번과 유사한 문제라고 볼 수 있다.

다만 리스트를 정수의 크기에 따라 정렬하는 sorted(),

리스트를 역순으로 반환하는 .reverse()

를 새롭게 묻는 문제였다.

'TIL' 카테고리의 다른 글

무리와 목표  (0) 2024.08.07
7/30  (0) 2024.07.30
3주차 목요일  (0) 2024.07.18
3주차 월요일  (2) 2024.07.15
강하주 공부 시작.  (2) 2024.07.12