ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 2024-01-03
    스파르타/TIL(Today I Learned) 2024. 1. 3. 23:15
    더보기

    SQL코드카타

     

    식품분류별 가장 비싼 식품의 정보 조회하기(SQL)

    https://school.programmers.co.kr/learn/courses/30/lessons/131116

    FOOD_PRODUCT 테이블에서 식품분류별로 가격이 제일 비싼 식품의 분류, 가격, 이름을 조회하는 SQL문을 작성해주세요. 이때 식품분류가 '과자', '국', '김치', '식용유'인 경우만 출력시켜 주시고 결과는 식품 가격을 기준으로 내림차순 정렬해주세요. 라는 문제이다.

    말이 조금 이상해서 이해한 대로 제출에 성공한 내용을 토대로하여 다시 간략히 설명하면

    식품 분류별로 가격이 가장 비싼 상품의 식품분류, 가격, 이름를 조회하는데 이때 카테고리가 '과자', '국', '김치', '식용유'인 경우만 출력시키고, 식품 가격을 기준으로 내림차순 정렬해달라는 문제이다.

    SELECT CATEGORY, Max(PRICE), PRODUCT_NAME
    FROM FOOD_PRODUCT
    GROUP BY 1
    Having CATEGORY in ('과자','국','김치','식용유')
    ORDER BY 2 desc
    

    가격은 정상적으로 나오는데 상품이름이 맞게 나오지 않아서 문제생김

     

     개별 직접 확인할 경우

    따라서 그냥 group을 써버릴 경우 name이 group안에서 젤 위에 있는 name가져와버림

    그래서 max_price에 맞는 이름을 가져오도록 써야하므로 먼저 하나를 해주고 연결시키고 컬럼!이런식으로 해야할듯

    SELECT CATEGORY,PRICE Max_PRICE,PRODUCT_NAME
    FROM FOOD_PRODUCT main
    WHERE CATEGORY in ('과자','국','김치','식용유')
            and PRICE = (SELECT max(PRICE) FROM FOOD_PRODUCT GROUP BY CATEGORY
                         HAVING CATEGORY = main.CATEGORY)
    ORDER BY 2 desc
    

    우선 카테고리별로 가장 비싼 금액을 구해준 뒤, 카테고리에 대하여 연결해 주었고, 필터 조건으로 카테고리가 과자, 국, 김치, 식용유 중에 해당 하는 것만 그리고 가격이 카테고리별 가장 비싼 금액과 동일한 것만 출력되도록 필터를 걸어중었다. 그리고 카테고리, 가격(카테고리안 최고 가격), 식품이름을 출력하도록 작성하였다.

    그리고 추가 여담으로 원래는 where절에서 서브쿼리문을 해줄 때 서브쿼리문의 테이블.연결할 컬럼=메인쿼리문의 테이블.연결할 컬럼 식으로 해야하는 것으로 알고 있었는데 어제 특강 내용에서 본 예시 중에 둘 중 하나만 테이블명.~을 해주고 하나는 그냥 바로 컬럼명으로 붙이는 것을 보았다 (확실한 것은 쿼리로 작성한 방식이다 반대로 하던 예도 봤던 것 같은데 조금 방식이 달랐던 것 같다 그래서 혹시나 해서 곧이곧대로 sub.카테고리=카테고리 해보았지만 이 방법은 에러가 났다 그래서 조금 있다가 다시 강의 복습하면서 반대 방식 예도 한 번 실제로 적용해보고 기록할 예정이다.)그래서 해본 결과 잘 되었다.

     

    5월 식품들의 총매출 조회하기(SQL) (inner join, sum, date_format , 날짜 필터링 총 정리?)

    https://school.programmers.co.kr/learn/courses/30/lessons/131117

    FOOD_PRODUCT와 FOOD_ORDER 테이블에서 생산일자가 2022년 5월인 식품들의 식품 ID, 식품 이름, 총매출을 조회하는 SQL문을 작성해주세요. 이때 결과는 총매출을 기준으로 내림차순 정렬해주시고 총매출이 같다면 식품 ID를 기준으로 오름차순 정렬해주세요.

    SELECT P.PRODUCT_ID, PRODUCT_NAME, SUM(PRICE*AMOUNT) TOTAL_SALES
    FROM FOOD_PRODUCT P inner join FOOD_ORDER O on P.PRODUCT_ID=O.PRODUCT_ID
    WHERE date_format(PRODUCE_DATE,'%Y')=2022 and date_format(PRODUCE_DATE,'%m')=5
    GROUP BY 1
    ORDER BY 3 desc,1
    

    처음에 ~에 대하여 라는 말이 없고 그냥 날짜범위만 주고 총매출 구하라길래 헤매다가 총매출은 그래도 가격*주문수 일 것 같아 하였는데 그 뒤 문제 내용 그대로 한 것 같지만 틀렸다고 나오길래 다른 분들 한 결과랑 비교를 하였는데 oder_id에 대해 그룹지어서 매출의 총합을 구해주었다는 것을 알고 수정하여 제출완료하였다. 그전까진 자세히 구체적으로 요구 했던 것 같은데, 이제는 문맥상? 요구같은 것도 융통성 있게 계산해줘야 하는 것 같다

    추가로 이 문제는 날짜를 필터링 하는 방법으로 like를 쓸 수도 있었지만 (like %2022-05%) like가 검색 능력이 떨어진다고 들은 바가 있어 date_format~방식으로 하여 필터해주었다, 두개 한번에 붙이는 방식은 잘 모르겠어서

    WHERE date_format(PRODUCE_DATE,'%Y-%m')=2022-5
    
    WHERE date_format(PRODUCE_DATE,'%Y-%m')=2022-05
    
    WHERE date_format(PRODUCE_DATE,'%Y-%m')=2022,5
    #이의 경우는 에러남
    #SQL 실행 중 오류가 발생하였습니다.
    #You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ',5
    #GROUP BY 1
    #ORDER BY 3 desc,1' at line 5
    
    WHERE date_format(PRODUCE_DATE,'%Y-%m')='2022-05'
    

    이런 방식으로 해봤지만 정상적으로 작동되는 것이 없어서 아무 값도 조회되지 않았고 제일 아래와 같은 방식으로 하니 정상적으로 검색 되었다(문자로 변환하는 방식이라 저렇게 되는 것으로 예상한다.)

    그리고 추가로 날짜 범위에 관하여 between으로 해두신 분도 있던데 기억해두면 좋을 듯하다

    Between in ‘2022-05-01’ and ‘2022-05-31’ 이런 식이였던 것같다

    where b.produce_date between '2022-05-01' and '2022-05-31’

    그외도 날자관련 함수인 month( month(컬럼)=5 )방식를 이용하여 하신 분도 계셨다 /year()도

    date_format말고도 to_char를 이용하여서 하시는 분도 있으셨다 (WHERE TO_CHAR(PRODUCE_DATE, 'YYYY-MM') = '2022-05’)

     

    더보기

    파이썬 코드카타

     

    예상 대진표(python) (2의 몇승 확인)

    https://school.programmers.co.kr/learn/courses/30/lessons/12985

    대강 토너먼트 형식으로 치러지는 경기가 있는데 두 명의 사람들이 몇라운드에서 만나게 될지 구하는 문제이다

    def grouping(N,num): #N:총명수,num:첫 번호, 쭉 이길시 배정될 그룹 리스트
        powers_of_two=[i for i in range(21) if 2**i<=N]#2의 몇승인지 파악하기 위해서
        n=powers_of_two[-1]
        group_list=[num]
        for i in range(1,n+1):
            if group_list[i-1]%2==0:
                group_list.append(group_list[i-1]//2)
            else:
                group_list.append((group_list[i-1]+1)//2)
        return group_list
        
    def solution(n,a,b):
        a_group=grouping(n,a) #a가 속하게 될 그룹
        b_group=grouping(n,b) #b가 속하게 될 그룹
        for i in range(len(a_group)):
            if a_group[i]==b_group[i]:
                return i
    

    위 메모들의 과정을 통해 각 라운드에 몇 번 그룹이 될지 계산해주고 서로 비교하여 가장 먼저 같은 그룹이 되는 라운드를 리턴하게 코드를 작성하였다.

    우선 입력해주는 총 인원 N에 대하여 2의 몇승인지 계산하고 해당 번호의 사람이 결승까지 쭉 이긴다면 배정될 그룹의 번호들을 쭉 기억해주는 함수를 만들어 주었고(처음 받은 번호는 0라운드의 번호 그룹이라고 생각해주었다)

    이 함수를 제출할 함수 안에 넣어서 사용하였으며 두 번호의 사람의 각각 그룹리스트를 비교하여 같은 그룹일 때 몇 라운드인지 리턴하게 하였다

     추가로 2의 몇승인지 계산해주는 알고리즘 같은게 따로 있을지 검색해봤으나 딱히 찾지 못하고 이 수가 2의 거듭제곱형태의 수인지 판별하는 것에 관련된 내용만 잔뜩나왔었다. 그래서 당장 필요하지는 않아 대강 가볍게 훑어만 봤는데 같이 제곱수인지 판별하는 것은 간단하여 바로 이해가 되었고 2의 n제곱인지 확인하는 것은 비트연산을 사용한다고 하면서 & 등의 기호가 있었는데 들어는 본적이 있었지만 정확히 몰라 이번 기회에 어떤 것인지나 알자는 느낌으로 찾아봤는데 우선 비트는 숫자를(문자도 가능한지는 정확히 모르겠다) 이진법으로 바꾸어서 연산하는 연산자인데 &는 대응 되는 비트가 모두 1이면 1반환 (AND역할), | (비트에서 OR역할), ^(XOR역할, 서로 다르면 1 반환), ~(NOT역할) << 지정한 수만큼 비트를 전부 왼쪽으로 이동시킴(left shitt연산, *2^수 만큼 한다고 생각하면 될듯),>>부호를 유지하면서 지정한 수 만큼 비트를 전부 오른쪽으로 이동시킴(right shift연산, /2^수 만큼 한다고 생각하면 될듯)가 있다고 한다.

     

    N개의 최소공배수(python) (LCM 최소공배수, 유클리드 호제법)

    https://school.programmers.co.kr/learn/courses/30/lessons/12953

    두 수의 최소공배수(Least Common Multiple)란 입력된 두 수의 배수 중 공통이 되는 가장 작은 숫자를 의미합니다. 예를 들어 2와 7의 최소공배수는 14가 됩니다. 정의를 확장해서, n개의 수의 최소공배수는 n 개의 수들의 배수 중 공통이 되는 가장 작은 숫자가 됩니다. n개의 숫자를 담은 배열 arr이 입력되었을 때 이 수들의 최소공배수를 반환하는 함수, solution을 완성해 주세요.

    def LCM(a, b): #유클리드 호제법으로 잘짜둔것 가져온것
        c,d = max(a, b), min(a, b)
        t = 1
        while t>0:
            t = c%d
            c, d = d, t
        return int (a*b/c)
    
    def solution(arr):
        lcm_num=1
        for i in range(len(arr)):
            lcm_num=LCM(lcm_num,arr[i])
        return lcm_num
    

    옛날에 했던 최대공약수와 최소공배수 구하는 함수를 가져와서 사용하였다(성능 좋은 유클리드 호제법을 적용하여 작성된 함수를 사용하였다. 이전에 다른 방식으로 만들다가 그만둔 것은 노션으로 작성해두질 않아서 기록이 없어서 해보고 싶다면 나중에 시간 드려서 다시 시도해봐야 할 것 같다 성능은 유클리드 호제법으로 짠 것보다 나쁘겠지만 유클리드 호제법을 매번 완벽하게 기억하고 있기는 조금 부담이 있기 때문에 보험용으로 한 번 해볼 생각이다.)

    일단 전에 사용한 함수를 그대로 가져와서 단순하게 초기값 1로 설정해둔 최소공배수 변수를 arr에 들어있는 수와 최소공배수 계산하여 최종값을 리턴하는 간단한 방식으로 하였다. arr길이가 15이하밖에 안되서 연산하는데 걸리는 시간을 크게 더 줄일 수 있는 생각은 하지 않았는데 만약 후에 나온다면 더 줄일 방법을 한번 고민해볼 예정이다.

     

    멀리 뛰기(python) (nCr 조합, 피보나치 수열 Fibonacci numbers)

    https://school.programmers.co.kr/learn/courses/30/lessons/12914

    칸을 뛰어넘는데 1칸, 또는 2칸씩만 넘을 수 있을 때 주어지는 칸에 대하여 몇 가지의 방법으로 도달할 수 있는지 푸는 문제이다.

    def nCr(n,r):
        num=1
        for i in range(1,r+1):
            num=num*(n-i+1)/i
        return int(num)
    def solution(n):
        answer = 0
        m=n//2 #0이 아닌 계산상 계산하면 되는 범위관련
        for i in range(m+1):
            answer+=(nCm(n-i,i)%1234567)
            
        return answer%1234567
    

    이렇게 하니 일단 간단한 숫자들에 대해서는 되었지만 큰 수에 대해서 하면 오버플로우가 나서 실패하거나 런타임에러가 난다. %는 합연산이 적용되기에 (a+b)%k=a%k+b%k

    더할 때 나머지로 해서도 해봤는데 여전히 오버플로우는 해결되지 않았다

    def nCm(n,m):
        #m>n인 경우 0되게 추가해줄려했는데 알아서 0나옴 이유는 모르겠음
        num=1
        for i in range(1,m+1):
            num=num*(n-i+1)/i
            print("계산중 ",num)
        print(num)
    

    nCm에서 n<m인 경우 0 이나오는게 맞긴한데 코딩해준 것 상 그리 나오지 않을 것 같은데 0이 나온다… 왜인지는 모르겠다..

    페르마의 소정리를 이용하면 오버플로우를 예방할 수도 있다고 하여 검색하여 찾아보고 내용은 이해했으나 어떻게 이용할지는 바로 떠오르지 않아 거기서 그만하고 패스하였다

    https://namu.wiki/w/피보나치 수열#s-7.1 <- 에서 '활용 경우의 수 파트'

    피보나치의 원리로도 해석이 가능해서 피보나치로 한번 풀어보겠는데 피보나치도 오버플로우 나는 것 같다고 생각하며 일단 해보았다.

    def fib(n):
        fibList=[1, 1]
        if n==1 or n==2:
            return 1
        for i in range(2,n):
            fibList.append( fibList[i-1] + fibList[i-2] )
            num=fibList[-1]
        return num
    
    def solution(n):
        answer = 0
        answer=fib(n+1)%1234567
        return answer
    

    전에 만들어두었던 피보나치 수열 함수를 가져와서 사용하니 바로 풀렸다..ㅎㅎ

    따로 별 조치를 안 했는데도 바로 오버플로우가 안 날 줄은 예상 밖이였다 조합의 계산방식이 근사하면 n*n-1이니 얼추 n^2에 근사하고 피보나치는 계산방식이 훨씬 적을 것 같기는 했다 정확한 복잡도? 수의 크기?는 기억이 안 나서 나중에 필요가 느껴진다면 다시 공부를 해볼듯하다.

    코드에서 fib(n+1)을 했는데 n이 아니라 n+1을 한 이유는 피보나치 수열은 1, 1, 2, 3… 이렇게 나열되는데 칸 뛰어넘는 방식은 1, 2, 3, …로 2번째 수부터 시작하기 때문에 보정해주기 위해 +1 해주었다. 위에 올린 링크에서는 칸이 아닌 계단으로 했는데 결국 대상만 다르지 수로 바꾸어 생각하면 둘 다 같은 내용이기에 혼동할 필요도 없을 듯하다.

     

    더보기

    데이터 리터러시 강의

    자세한 내용을 깔끔히 정리하기에는 시간이 오래 걸릴 듯하여 우선적으로 배운 내용의 큰 키워드에 대하여 완강때 적은 내용을 옮겨 적어두었다. 현재는 강의자료가 예시를 포함하여 깔끔히 잘 되어 있는 듯하여 추가로 정리할 생각은 안드는데 후에 만약 따로 깔끔히 더 줄이고 정리한다면 따로 정리하여 올려야 할듯하다.

    데이터 리터러시가 어떤 것인지에 대하여 배웠고, 데이터 분석에 대하여 어떤 착각을 하는지 주의할 부분들을 배웠고 데이터 리터러시를 활용을 어떻게 하면 될지, 데이터 리터러시가 필요한 이유가 무엇인지에 대하여 배웠습니다 또 문제 정의란 무엇이며 문제 정의를 어떻게 내려야하며, 내리는 방법에는 어떤 것이 있다는 것을 배웠습니다 데이터의 유형에는 정량적 데이터와 정석적 데이터가 있으며 정량적 데이터를 활용하는 법에 대해 배웠습니다 그리고 지표가 무엇인지에 대하여 배웠고 지표는 어떻게 설정해야하는지 주요 지표들과 북극성 지표를 배웠습니다 마지막으로 데이터 분석을 통한 결과를 얻음으로 내릴 수 있는 결론은 결과와 어떻게 다르며, 그것을 어떻게 내려야할지 어떻게 하면 잘 정리가 되는지에 대하여 배웠습니다

     

    오늘은 오전에 SQL개인과제 해설 강의, 발제 등의 실시간 zoom강의가 있어 개인적으로 혼자 공부하는 시간이 다른 날에 비해 상대적으로 적었다. 그리고 데이터 리터러시의 강의를 들었는데 데이터 분석을 할때 분석에 앞서 어떻게 문제를 정의할 것인지 생각하고 분석 후에는 이것을 어떻게 왜 라는 생각을 하면서 결론을 내릴 수 있어야 한다는 것을 다시금 깨닫게 되었다. 개인과제 해설 강의 관련하여는 아직 특강부분도 복습 및 정리를 덜한 부분이 있어 못하였기에 하고나서 같이 이어서 할 것 같다.

    발제는 좋은 내용이긴 했는데 이것도 TIL에 적기에 적합한 내용인지는 살짝 애매하다고 생각되어 조금 더 생각해보고 판단 되는 대로 정리하거나 TIL에서는 패스하거나 할듯하다.

    '스파르타 > TIL(Today I Learned)' 카테고리의 다른 글

    2024-01-05  (1) 2024.01.05
    2024-01-04  (0) 2024.01.04
    2024-01-02  (1) 2024.01.02
    2023-12-30~2023-01-01  (0) 2024.01.02
    2023-12-29  (1) 2023.12.29
Designed by Tistory.