ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 2023-12-30~2023-01-01
    스파르타/TIL(Today I Learned) 2024. 1. 2. 22:27

    (연휴간 풀었던 코드카타와 과제하면서 찾은 내용 등등)

    생각을 해보니 SQLD 강의 내용을 모두 적기에는 양도 너무 많고 크게 의미가 없을 듯하여 복습할 때 중요하거나 헷깔렸다고 판단되는 내용 위주로 적도록 할려고 한다. 우선 강의를 듣고 마무리로 적어 냈던 진짜 간단히 요약한 내용을 쭉 모아서 적어두기만 할려고 한다 (뒷 강의로 갈수록 실습내용 위주거나, 읽어보라고 하셔서 급하게 듣느라 자세히 안보고 큼직큼직하게만 보고 적어 냈던 부분들이라 별내용이 없기는 하다)

    더보기

    SQLD 7~16주차 내용

    7주차는 적어놨던 것이 날라가서 패스하겠다

    8주차

    insert inito 테이블 값를 이용하여 데이터를 삽입할 수 있다. update 테이블 set 수정컬럼이름=수정값 하면 내용 수정가능 하지만 where절 꼭 넣기 안 넣으면 해당 컬럼 의 모든값이 수정값으로 변해버림 delete [from] 테이블 이름 하면 테이블 지울수 있는데 where절 꼭 붙여서 하고 왠만하면 select문으로 먼저 조회해서 확인한 뒤 실행하기 delete는 그래도 DML이라 자동 comit아니면 rollback이 가능해서 복구가 되는데 truncate는 DDL이라 무조건 자동 comit되기에 rollback이 되지 않으니 주의 select는 조회하는 방법으로 여러 방식으로 다양한 옵션과 함께 많이 쓰임 컬럼 별칭 붙일때 as 붙이고 해도 되고 그냥 생략하고 한칸 띄어쓰고 해도 됨, distinct는 쿼리 결과에서 중복된 값을 제거하여 고유한 값만을 반환하도록 하는 역할함 그외 산술 연산자는 흔히 아는 수학적 기호들을 똑같이 쓰며 number이거나 문자형식이지만 숫자의 내용인 경우 가능하나 문자형식일 때는 그리 권장하지 않음 합성연산자는 ||를 이용하거나 concat을 이용하여 여러 문자를 하나로 만들 수 있음

    9주차

    필요한 데이터만 필터링 하는 where에 대하여 배웠으며 Rownum과 Rowid, 여러 단일행 함수에 대해 배웠다

    10주차

    그룹을 지어 집계를 할 수 있도록 해주는 group by와 그 그룹을 집계함수를 이용하여 조건에 따라 그룹을 필터링 하는 having by, 정렬하는 order by, comit과 rollback하는 TCL, 권한부여하는 DCL에 대하여 배웠다

    11주차

    join에 관하여 여러가지 배웠다 (대체로 그냥 쭉 읽어보라는 내용이 많아서 나중에 다시 복습할 때 제대로 정리 해야할듯)

    12주차

    집합 연산자, 서브쿼리, 뷰에 대하여 배웠다(직접 읽어보고 실습해봐야 잘 이해 되는 내용들이 많아서 직접 해봐야 알 것 같다.)

    13주차

    여러 그룹함수와 window함수, 절차형 SQL을 통해 사용자 정의 함수, 프로시저, 트리거를 만들 수 있음을 배웠다. (마찬가지로 직접 해봐야 알듯하다)

    14주차

    어떤 방식으로 SQL 쿼리를 처리하고 데이터를 검색할지 결정하는데 도움을 주는 도구인 옵티마이저와 그 옵티마이저가 사용자가 SQL을 실행하여 데이터를 추출하려고 할 때 수립하는 작업 절차인 실행계획, 검색조건에 부합하는 데이터를 빠르게 검색할 수 있도록 돕는 인덱스에 대하여 배웠다. 그리고 추가로 테이블 을 합치는 조인에 관련하여 조인 수행 원리에 대하여도 배웠다.

    15,16은 문제 풀이 해설이라 패스한다

     

    더보기

    SQL코드카타

     

    성분으로 구분한 아이스크림 총 주문량(SQL) (join, group by, sum)

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

    상반기 동안 각 아이스크림 성분 타입과 성분 타입에 대한 아이스크림의 총주문량을 총주문량이 작은 순서대로 조회하는 SQL 문을 작성해주세요. 이때 총주문량을 나타내는 컬럼명은 TOTAL_ORDER로 지정해주세요. 라는 문제이다.

    SELECT INGREDIENT_TYPE, sum(TOTAL_ORDER) TOTAL_ORDER
    FROM FIRST_HALF f inner join ICECREAM_INFO i on f.flavor = i.flavor
    GROUP BY 1
    ORDER BY 2
    

     

    루시와 엘라 찾기(SQL)

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

    동물 보호소에 들어온 동물 중 이름이 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 1
    

     

    조건에 맞는 도서 리스트 출력하기(SQL) (date_format)

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

    BOOK 테이블에서 2021년에 출판된 '인문' 카테고리에 속하는 도서 리스트를 찾아서 도서 ID(BOOK_ID), 출판일 (PUBLISHED_DATE)을 출력하는 SQL문을 작성해주세요. 결과는 출판일을 기준으로 오름차순 정렬해주세요. 라는 문제이다.

    SELECT BOOK_ID,
        date_format(PUBLISHED_DATE,'%Y-%m-%d') PUBLISHED_DATE
    FROM BOOK
    WHERE date_format(PUBLISHED_DATE,'%Y-%m-%d')=2021 and CATEGORY = '인문'
    ORDER BY 2
    

     

    평균 일일 대여 요금 구하기(SQL) (ROUND)

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

    CAR_RENTAL_COMPANY_CAR 테이블에서 자동차 종류가 'SUV'인 자동차들의 평균 일일 대여 요금을 출력하는 SQL문을 작성해주세요. 이때 평균 일일 대여 요금은 소수 첫 번째 자리에서 반올림하고, 컬럼명은 AVERAGE_FEE 로 지정해주세요. 라는 문제이다.

    SELECT ROUND(avg(DAILY_FEE),0)
    FROM CAR_RENTAL_COMPANY_CAR
    WHERE CAR_TYPE = 'SUV'
    

    Round(컬럼, 자릿수) 자리수로 적은 부분까지 남기고 반올림 해줌, 자리 수 넣지 않을 경우 소수점 모두 반올림해버림

     

    더보기

    파이썬 코드카타

     

    둘만의 암호(python)

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

    대강 제외 목록을 정하고 알파벳을 정해진 숫자만큼 제외 목록에 있는 알파벳을 제외하고 뒤의 순서의 알파벳으로 치환한다는 암호 규칙을 정하여 암호문자열, 제외목록, 몇개를 입력받아 해독하는 문제이다.

    def solution(s, skip, index):
        answer=''
        able_list=[chr(ord('a')+i) for i in range(ord('z')-ord('a')+1)] #가능한 목록
        for i in skip: #스킵에 있는 얘들 제거
            able_list.remove(i)
        for j in range(len(s)):
            answer+=able_list[(able_list.index(s[j])+index)%len(able_list)]
            
        return answer
    

    매우 고민하여 풀었었으나, 결국 해결이 안되 반례도 찾지못하여 포기하고 다른 분 하신 걸 보고 그것 바탕으로 작성함(처음에 리스트로 만들어서 그 안에서 직접 돌릴 생각은 했으나, %를 떠올리지 못하여서 포기했었던 방법임)

    def solution(s, skip, index):
        trans = list(s) #문자를 변환할 때 저장할 변수 #a~z : 97~122
        skip_list=sorted([ord(i) for i in skip]) #skip에 해당하는 문자 아스키코드
        for i in range(len(trans)):
            move=0
            for j in range(index):
                move+=1
    
                while (ord(trans[i])+move > ord("z") or ord(trans[i])+move in skip_list):
                    if ord(trans[i])+move > ord("z"): #z에서 다시 넘어갈경우 추가계산
                        move-=26
                    while ord(trans[i])+move in skip_list:
                        move+=1
                        
            trans[i]=chr(ord(trans[i])+move)
            
        return ''.join(trans)
    

    이것이 위의 방식을 떠올리다가 마지막 %부분을 생각을 못해서 다른 방식을 생각하여 원래 만들었던 방식인데 8번테스트 케이스를 해결하지 못 하다가 질문하기에 혹시나 해서 올려놨는데 새벽 사이 어느 분이 반례를 달아주셔서 그 부분을 통해 해결하였다 (전체적으로 move가 일어나면 (그러니까 다른 글자로 변환) 이것이 z를 넘어가는 것인지와 이것이 skip에 있는 문자인지 계속 체크해 주어야하는데 기존 코드에서는 )

    문제 해결 전 코드에 대해서도 첨부하면 

    def solution(s, skip, index):
        trans = list(s) #문자를 변환할 때 저장할 변수 #a~z : 97~122
        skip_list=sorted([ord(i) for i in skip]) #skip에 해당하는 문자 아스키코드
        for i in range(len(trans)):
            move=0
            for j in range(index):
                move+=1
                if ord(trans[i])+move > ord("z"): #z에서 다시 넘어갈경우 추가계산
                    move-=26
                while ord(trans[i])+move in skip_list:
                    move+=1
    				#여기 부분
            if ord(trans[i])+move > ord("z"): #출력전 최종 z에서 다시 넘어갈경우 추가계산
                move-=26
    					#여기부분2
                while ord(trans[i])+move in skip_list: #z있어서 스킵한다고 넘어가면 스킵해야할 것 검사안해서 스킵안될수 있으니
                    move+=1
            trans[i]=chr(ord(trans[i])+move)
    				#여기부분까지
        return ''.join(trans)
    

    #여기부분~#여기부분까지 를 제일 처음에는 넣지 않아 “x”, “z” 2 와 같이 skip리스트가 있어 move를 더 추가해주었지만 그로 인해서 z를 넘어갈 경우 더 이상 index에 의한 이동이 없어 z넘어갈 경우 a로 바꿔주는 과정을 하지못하여 원래 a가 나와야 맞게나오는데 {가 나오게 되어(z가 122, {가 123이다) 여기부분~여기부분2까지 추가해주어 해결하였지만, 그 다음으로 "ybcde", "za", 1 의 케이스 같이 skip에 z가 포함되어 있어 z에서 +1 해주고 z를 넘어가서 a로 바꾸어주었지만 추가로 skip에 a를 포함하고 있는 경우 a와 그외 추가적인 skip에 있는 것들까지 확인을 해서 해당 문자일 경우 move를 더 해줘야하는데 z를 넘을 경우 a로 보내는 작업을 하고나서는 다시 스킵에 해당하는 문자인지 확인하는 작업이 없기에 acdef가 나와버리는데 해결하여 올바르게 나온다면 bcdef가 나온다. 하지만 여기서 더이상 알려진 반례도 없이 제출하였을 때 8번케이스가 실패하였는데 어느 감사하신 분이 올려주신 반례로 "yyyy","za",2 의 경우 “cccc”가 나와야하는데 내 코드로 할경우에는 “bbbb”가 나온다고 알려주셨다. 이는 y에 대하여 2번 이동해줘야하니 우선 코드에 직접 순서대로 계산해보면 y에서 한번 이동하여 z, z를 아직 넘지는 않았으니 그다음 skip에 있는지 확인하면 있으므로 한번이동해서 {이고 없으니 한번더 index에 의해 이동해주면 그다음인 |가 나오고z를 넘었으니 a로 보내면(-26하면) b가 되고 그럼 더이상 z를 넘지 않으니 그대로 출력하게 된다.(이 경우에도 a가 스킵에 있어서 넘어가줘야하는 부분이 포함되지 않아 올바른 결과가 나오지 않았다) 그래서 생각해보면 index에 의해 이동하거나 skip에 포함되어 있어 이동하거나 z를 넘어서 이동할 경우 즉 move가 발생할 때 항상 z를 넘는지 와 이동 후 해당 문자가 skip아나에 있는 지를 계속 확인 해주어야하므로 해결한 코드 대로 if과 while문 그리고 if과 그안에 while문으로 되어있던 것을 큰while문으로 z를 넘거나 skip이 발생해야하는 경우에는 반복되게 해주고 그안에 각각 z를 넘을 경우 변환과 skip안에 해당하는 문자일 경우 넘어가는 것을 하도록 수정해주었더니 문제가 해결되었고 무사히 제출을 할 수 있었다.

    +추가 여담으로 원래는 확인하는 양을 줄이고자 filter함수를 이용하여 필요한 부분만 남긴 리스트를 만드는 식으로 해볼려고 했으나 연산이 그렇게 줄지도 않는 것 같고 필터링되는 양이 만드는데 걸리는 연산시간에 비해서 유의미하게 이득을 가져온다 생각이 되지않았고(문제의 주어진 제한조건상 skip의 길이가 10이 최대였음) 막상 그렇게 필터링한 리스트를 만들어도 그렇게 많이 쓰이지 않았기에 최종 코드들에서는 제외하였으나 해보고 싶어서 해볼때는 대강 이런 형태를 만들었다

    def skip_filter(x,string,num): 
        return (ord(string) <=x<= ord(string)+num) or (ord(string)-26 <=x<= ord(string)+num-26)
    
    check_list=list(filter(lambda x: skip_filter(x,trans[i],index), skip_list))
    

    위 같은 조건 함수를 정의하고, 아래와 같이 사용했었다

    +파이썬 리스트 비교를 테스트 해본 내용이다.

    >>> a=[1,2,3,5]
    >>> a>10
    Traceback (most recent call last):
      File "<pyshell#25>", line 1, in <module>
        a>10
    TypeError: '>' not supported between instances of 'list' and 'int'
    >>> a<10
    Traceback (most recent call last):
      File "<pyshell#26>", line 1, in <module>
        a<10
    TypeError: '<' not supported between instances of 'list' and 'int'
    >>> b=[1,2,3,4]
    >>> a>b
    True
    >>> a<b
    False
    >>> b=[2,3,4,5]
    >>> a>b
    False
    >>> a<b
    True
    >>> b=[1,2,5]
    >>> a>b
    False
    >>> a<b
    True
    >>> a=[5]
    >>> a>b
    True
    >>> a<b
    False
    >>> a=[3]
    >>> a>b
    True
    >>> a<b
    False
    >>>
    

     이것 저것 직접 쳐서 테스트 해봤는데 완전히 기억하지는 못할 것 같아 기록으로 남겨둔다

     

    햄버거쌓기(python) (리스트 문자열로 변환하는 방법)

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

    대강 재료 순서대로 있을때만 햄버거를 쌓고 쌓는다고 사용하면 그자리 비워지면서 붙여지고 또 있다면 쌓고 그런식으로 몇번가능한지 묻는 문제

    def solution(ingredient):
        answer = 0
        s_ing=''.join(str(i) for i in ingredient) #리스트를 문자열로 변환
        #원래 알던 대로면 [str(i) for i in ingredient]이지만 생략가능한듯
        order='1231'#햄버거 쌓을 수 있는 재료순
        while s_ing.count(order)>0 :
            answer+=s_ing.count(order)
            s_ing=s_ing.replace(order,'') #쓴재료는 제거
        return answer
    

    처음에 이렇게 했더니 들어온 순서대로 완성가능할 경우 쌓아서 써야하기 때문에 [1, 2, 1, 2, 3, 1, 3, 1, 2, 3, 1, 1]의 순서로 들어오면 2가 나와야하는데 전체 다 쌓여있다고 보고 쏙쏙 빼서 만들었기에 3이 나와 잘못된 결과를 얻음

    def solution(ingredient):
        answer = 0
        s_ing=''.join(str(i) for i in ingredient) #리스트를 문자열로 변환
        #원래 알던 대로면 [str(i) for i in ingredient]이지만 생략가능한듯
        order='1231'#햄버거 쌓을 수 있는 재료순
        while s_ing.count(order)>0 :
            answer+=1
            s_ing=s_ing[:s_ing.index(order)]+s_ing[s_ing.index(order)+len(order):]
        return answer
    

    슬라이싱하는 것을 이용해서 빼줬더니 역시 예상대로 time out이 되었다

    def solution(ingredient):
        answer = 0
        s_ing=''#.join(str(i) for i in ingredient) #리스트를 문자열로 변환
        #원래 알던 대로면 [str(i) for i in ingredient]이지만 생략가능한듯
        order='1231'#햄버거 쌓을 수 있는 재료순
        for ing in ingredient:
            s_ing+=str(ing)
            if len(s_ing)>=len(order):
                if s_ing.count(order)>0:
                    answer+=1
                    s_ing=s_ing.replace(order,'')
        return answer
    

    직접 한개 씩 추가하는 방식으로 해주었는 데 혹시나 했지만 똑같이 time out 되었다.

    둘중 비교해보자면 그래도 리스트로 한 것이 시간초과로 실패한게 적었다(리스트 4~8번,12)(하나씩 직접 3~9번,11,12번)

    https://chat.openai.com/share/06bab85f-16c1-4e0a-9661-486861e468be

    chatGPT에게 성능 개선안에 대해 알려달라고 하니 계산 반복하여 사용하는 값은 값이 계속 같은면 그냥 변수로 하여금 저장해두고 사용하길 권장하였고 매번 모두를 검색하지 않고 검색하는 부분을 최소화하여 검색하기를 추천하였다

    그리고 문자열과 리스트에 관하여 성능은 크게 차이 나지 않으며 특정 연산에 따른 차이가 다소 날 수는 있으나 크게 차이 나지 않는다고 하였다.

    def solution(ingredient):
        answer = 0
        now=[] #현재 쌓여있는 재료 리스트
        order=[1,2,3,1] #햄버거 쌓을 수 있는 재료순
        order_len=len(order)
        for ing in ingredient:
            now.append(ing)
            if len(now)>=order_len:
                if now[-order_len:]==order:
                    answer+=1
                    del now[-order_len:]
        return answer
    

    최종 제출 코드 리스트로 순서대로 있는지 확인하는 과정이 어렵다고 생각해 굳이 문자열로 바꿔서 하였으나 할 방법 찾아서 굳이 문자열로 한 번 더 바꾸기보단 그대로 리스트로 연산하였음, 검색 범위를 끝의 햄버거 재료 갯 수 4개만 확인해주었다. 그랬더니 연산이 빨라져 시간이 매우 단축되었다

     

    성격 유형 검사하기(python) (딕셔너리)

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

    대강 MBTI같은 새로운 분류 유형의 성격 유형 검사인데, 설문하여 나온 결과에 따라 유형을 판단해주는 문제이다.

    def solution(survey, choices):
        answer = ''
        score={'R':0,'T':0,'C':0,'F':0,'J':0,'M':0,'A':0,'N':0}
        
        for i in range(len(survey)):
            if choices[i] in [1,2,3]: #1,2,3으로 응답시 앞에 문자에 점수
                score[survey[i][0]] += 4-choices[i]
            elif choices[i] in [5,6,7]: #5,6,7으로 응답시 뒤에 문자에 점수
                score[survey[i][1]] += choices[i]-4
        #문자별 점수 비교 및 결정
        #RT
        if score['R'] >= score['T'] :
            answer+='R'
        else:
            answer+='T'
        #CF
        if score['C'] >= score['F'] :
            answer+='C'
        else:
            answer+='F'
        #JM
        if score['J'] >= score['M'] :
            answer+='J'
        else:
            answer+='M'
        #AN
        if score['A'] >= score['N'] :
            answer+='A'
        else:
            answer+='N'   
        return answer
    
    #항상 대문자라는 제한조건이 안 보이던데 안 넣어도 될련지
    

    딕셔너리를 굳이 쓸 필요 없이 리스트를 써도 됬겠지만 가독성이 더 좋아보이고 딕셔너리 형태에 익숙해질겸 딕셔너리 형태를 사용하여 작성하였다.

     

    바탕화면 정리(python)

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

    대강 내용은 바탕화면 파일 정리한다는 내용이지만 풀이에는 상관없고, 파일들이 나열되어있는 것을 한번에 드래그해서 삭제하고 싶은데 그 드래그의 범위를 최소로 할려면 어느 지점부터 어느 지점까지 드래그해야할까 묻는 문제이다.

    def solution(wallpaper):
        rdx=50      #최소 x좌표
        rdy=50      #최소 y좌표
        lux=0       #최대 x좌표
        luy=0       #최대 y좌표
        temp_x=0    
        temp_y=0    
        
        #대강 크게 최저위치와 최고위치로 사각형 그리면 최소범위 잡은 것일테니
        for x in range(len(wallpaper)): #wallaper 갯수가 곧 x(행의 수)
            for y in range(len(wallpaper[0])): #wallaper한 원소의 글자수가 곧 y(열의 수)
                if wallpaper[x][y]=='#': #해당 위치에 있을경우
                    if x<rdx:
                        rdx=x
                    if y<rdy:
                        rdy=y
                    if x+1>lux:
                        lux=x+1
                    if y+1>luy:
                        luy=y+1
                                
        answer = [rdx,rdy,lux,luy]
        return answer
    

    파일이 존재하는 위치 탐색, 최소위치와 최대위치를 찾는게 관건이고 나머진 간단할 것 같기는 했는데 생각보다 더 간단히 끝나서 뭔가 잘못한 건 아닐지 고민이 됬는데 잘 제출되었다.

     

    더보기

    Mysql 관련 내용들

     

    Mysql type확인하는 법

    #SHOW COLUMNS
    
    #전체 field 보기
    SHOW COLUMNS FROM 테이블;
    
    #특정 field만 보기
    SHOW COLUMNS FROM 테이블 (LIKE같은 조건);
    
    
    #desc
    desc 테이블;
    
    
    #information_schema
    #전체 field 보기
    SELECT DATA_TYPE FROM information_schema.COLUMNS WHERE TABLE_NAME=테이블;
    
    #특정 field만 보기
    SELECT DATA_TYPE FROM information_schema.COLUMNS WHERE TABLE_NAME=테이블 AND COLUMN_NAME=컬럼;
    
    #전체 field 보기
    SELECT COLUMN_TYPE FROM information_schema.COLUMNS WHERE TABLE_NAME=테이블;
    
    #특정 field만 보기
    SELECT COLUMN_TYPE FROM information_schema.COLUMNS WHERE TABLE_NAME=테이블 AND COLUMN_NAME=컬럼;

     reference

    MySql column의 type check 방법

     

    Mysql null확인 공백 확인

    null 체크 할 때는

    컬럼 IS NULL 
    컬럼 IS NOT NULL

     를 이용한다.

     

    Empty 체크 할 때는

     null이 값의 존재 유무라면 empty는 값이 비어 있는가의 유무로 값이 없는 것과 비어있는 것을 잘 구분해야할 것 같다

    컬럼 = ''
    컬럼 != ''

    를 이용하여 구별한다 

     

    SQL DELETE(행 삭제하기)

    DELETE FROM genders WHERE 조건식;

     

     를 해주면 삭제가 되는데 주의할 점은 where절 등 꼭 조건을 붙여서 delete하자

    그렇지 않으면 해당 컬럼의 값이 모두 날라가는 끔찍한 경험을 겪을 수 있다고 한다.

    그리고 DML이라 commit를 해주어야 적용되는데 현재 내가 하는 환경에서는 auto-commit이 설정되어있어서 바로 되었다(나중에 auto-commit 설정 관련해서도 어떻게 하는지 찾아봐야할 듯 하다)

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

    2024-01-03  (2) 2024.01.03
    2024-01-02  (1) 2024.01.02
    2023-12-29  (1) 2023.12.29
    2023-12-28  (1) 2023.12.28
    2023-12-27  (0) 2023.12.27
Designed by Tistory.