ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 2023-12-28
    스파르타/TIL(Today I Learned) 2023. 12. 28. 23:27
    더보기

    SQLD강의 3주차 내용 요약정리

    데이터 모델링의 요소 4가지인 엔티티, 속성, 관계, 식별자에 대하여 배웠다. 엔터티는 데이터 모델의 핵심 구성요소이며, 각각 데이터 모델의 개체라고 생각하면 될 것같다. 인스턴스는 인스턴스는 데이터베이스 테이블에 저장된 특정한 데이터 내용의 전체 집합 즉, 하나의 row(행)을 의미하는데 엔티티가 여러 인스턴스로 이루어져있다고 생각할 수 있다. 엔터티의 특징으로는 업무에서 필요로 하는 정보, 식별 가능 여부, 인스턴스의 집합, 업무 프로세스에 의해 활용되어야 함, 속성을 포함해야 함, 관계의 존재를 가지고, 분류방식으로는 유/무형에 따른 분류로 유형, 개념, 사건 엔터티로 나눌 수 있고, 발생시점으로 분류할 경우 기본/키, 중심, 행위 엔터티로 나눌 수 있다. 엔티티는 고유한 이름을 갖도록 특징한 규칙 기반으로 이름을 짓는다. 이어서 속성은 엔터티 또는 인스턴스가 가진 어떤 성질을 의미한다. 업무에서 필요로 하는 인스턴스로, 관리하고자 하는 의미상 '더 이상 분리되지 않는 최소의 데이터 단위'라고 할 수 있다. 엔터티의 개념은 사람, 장소 등 명사에 해당하고 업무상 관리가 필요한 관심사에 해당하며, 저장이 되기 위한 어떤 것이다. 엔터티와 인스턴스, 속성, 속성 값의 관계를 얘기하면 한개의 엔터티는 두 개 이상의 인스턴스의 집합이어야 하고, 한 개의 엔터티는 두 개 이상의 속성으로 구성된다 그리고 한 개의 속성은 한 개의 속성값을 갖는다. 속성의 표기법은 앞서 했던 대로 IE와 Barker표기법이 있고 속성의 특징으로는 업무에서 필요로하며, 속성은 의미상 더 이상 분리되지 않는 그 자체로 독립성을 유지한다. 엔터티를 설명하고 인스턴스의 구성요소가 되며 정규화 이론에 기반을 두고 주식별자에 함수적 종속성을 가져야 한다. 속성의 분류는 특징에 따라 분류를 하면 기본, 설계, 파생 속성으로 분류가 되고, 엔터티 구성 방식에 따른 분류를 하면 PK, FK, 일반 속성으로 분류된다. 추가로 각 속성이 가질 수 있는 값의 범위를 도메인이라고하며, 속성의 명명도 엔터티 처럼 고유한 이름을 갖도록 특정 규칙을 기반으로 이름을 짓는데 엔터티와 차이점은 각 다른 엔터티에서 같은 이름의 속성이 존재해도 된다는 것이다. 중복 되지 않으면 좋으나 여러 이유로 인해 오히려 같은 의미는 같은 이름을 같는 것이 나은 경우도 있다. 세번째로 관계는 상호 연관성이 있는 상태라고 할 수 있다 조금 더 길게 말하면 엔터티와 인스턴스 사이의 논리적인 연관성으로서 존재의 형태 행위로서 서로에게 연관성이 부여된 상태라고 할 수 있다. 관계의 연결을 관계의 페어링이라고 한다. 관계의 종류는 어떻게 분류를 하냐에 따라 분류가 가능한데 소속/포함의 의미를 가지는 존재에 의한 관계와 행동/행위의 결과로 나타나는 행위에 의한 관계가 있다. ERD에서는 존재적 관계와 행위에 의한 관계를 구분하지 않고 표현했다면 클래스 다이어그램(UML)에서는 이를 구분하여 연관 및 의존 관계로 표현한다. 관계명은 가나단히 포함한다, 소속된다 등이 있다 보면 될 것같으며, 관계의 표기법은 관계차수에따라 1:1, 1:N, M:N으로 나누는데 IE의 경우 |은 1개 까치발처럼 3갈래표시는 여러개 O는 0개라는 의미이며 O은 관계 선택 사양에서 필수가 아닌 선택이라는 의미를 나타내기도하며 barker의 경우는 갯수에 관한 표시는 IE와 동일하게 여러개라는 의미의 까치발 세갈래만이 존재하고 별도 표시는 없으며 관계 선택 사양에서는 점선의 경우 선택이고 실선의 경우는 필수라는 의미이다. 관계 정의 시 체크 사항은 두 엔터티 사이에는 관심 있는 연관 규칙이 존재하는지 여부, 두 개의 엔터티 사이에 정보의 조합이 발생하는지 여부, 업무 기술서, 장표에 관계 연결에 대한 규칙이 있는지 여부, 업무 기술서, 장표에 관계 연결을 가능하게 하는 '동사(Verb)'가 있는지 여부이다. 마지막으로 식별자에 대하여 얘기를 하면 엔터티의 인스턴스를 구분 가능하게 만들어주는 대표 격인 속성을 식별자라고 하며 식별자의 분류는 어떻게 보느냐에 따라 대표성 여부로 주식별자/보조식별자, 스스로 생성여부따라 내부식별자/외부식별자, 단일속성 여부에 따라 단일식별자/복합식별자, 대체여부에따라 본질식별자/인조식별자가 있으며, 주식별자의 특징으로는 유일성, 최소성, 불변성, 존재성이 있다. 식별자의 표기법으로는 IE의 경우 점선으로 이어지면 비식별자로 쓴다는 의미 실선은 식별자로 쓴다는 의미이며, barker는 |을 표시하면 식별자로 쓴다는 의미이다.

     

    더보기

    SQLD강의4주차 내용 요약정리

    '성능 데이터 모델링'이란 데이터베이스 성능 향상을 목적으로 하는 작업을 의미한다. 성능 데이터 모델링 수행시점은 분석/설계 단계때 부터 해야 비용을 최소화할 수 있다. 정규화를 통한 성능 향상 전략데이터에 대한 중복성을 제거하여 성능을 향상시키는 것을 의미한다. 정규화를 통해 특정한 칼럼으로 분산되어있던 의미를 하나로 집약시킬 수 있어 테이블의 칼럼 수가 줄어들어 데이터 용량을 줄일 수 있다. 여러 테이블에 분산되어 있지 않으면 불필요하게 여러번 조회 하는 일이 없어져 조회 과정에서의 불필요한 연산을 줄일 수 있기 때문에 성능 향상에 기여하지만, 정규화를 한다고 해서 꼭 성능이 향상되는 것은 아니며 성능이 될 수도 혹은 아닐 수도 있다. 정규화의 이점은 데이터의 유연성을 올리고(응집도는 높이고 결합도는 낮춘다), 데이터의 재활용성과 데이터의 중복 최소화이다. 정규화는 함수적 종속성을 근거로 하는데, 제 1정규화는 한 속성에 여러 개의 속성이 포함되어 있거나 같은 유형의 속성이 여러 개로 나눠져있는 경우 해당 속성을 분리한다. 제 2정규화는 제 1정규화를 만족시키고 PK가 아닌 모든 칼럼은 PK 전체에 종속시킨다(제 2정규화를 만족하지 못할 경우 갱신시 문제가 생길 가능성이 높아진다). 제 3정규화는 제2정규화를 만족시키고 일반 속성 간에도 함수 종속 관계가 존재하지 않아야 한다. 반정규화는 정규화가 방법이 정해져있는데 그 방법에 맞지 않으면 반정규화라고 볼 수 있다. 실제 상황에서는 읽기가 쓰기보다 많이 일어나기 때문에 읽기, 즉 조회의 성능을 올릴 수 있는 반정규화도 많이 쓰인다.

     

    더보기

    SQLD강의5주차 내용 요약정리 (다소 이해도가 떨어져서 복습 꼭 필요할듯)

    대량 데이터가 늘어남에 따라 성능이 저하된다 수평/수직분할처럼 테이블을 분할하면 해결이 어느정도 가능한데 그래도 완전히 해결할 수는 없다고 할 수 있다. 대용량 데이터에서 발생할 수 있는 대표적인 성능 저하 현상은 로우 체이닝과 로우 마이그레이션이 있다. 분할 방법으로는 수평 분할에 속하는 범위분할, 목록 분할이 있고 해시분할, 합성 분할이 있다. 데이터베이스의 구조와 성능은 슈퍼타입과 서브타입이 있는데 슈퍼타입은 공통적인 속성이고 서브타입은 자신만의 속성을 의미한다. 슈퍼타입/ 서브타입 모델 변환 방법은 하나의 테이블로 병합하는 슈퍼타입(single/all in one), 슈퍼타입과 서브타입 테이블로 변환하는데 도출된 각 서브타입에 슈퍼엔터티에 있던 칼럼을 공통적으로 가지고있는 서브 타입(plus/super+sub), 슈퍼와 서브 각 개별 테이블로 변환하는 개별 타입이 있다. 그리고 PK의 순서에 따라서도 성능에 영향을 줄 수 있다. 물리적으로는 분산되어 있지만 논리적으로는 하나의 데이터베이스를 다루는 것처럼 하는 분산데이터는 분할, 위치, 지역사상, 중복, 장애, 병행 6가지의 투명성을 가지고 있으며 지역 자치성, 점증적 시스템 용량 확장, 신뢰성 & 가용성,효용성 & 융통성,빠른 응답 속도 & 통신 비용 절감,데이터의 가용성 & 신뢰도 증가,시스템 규모의 적절한 조절,각 지역 사용자의 요구 수용 증대라는 장점과 소프트웨어 개발 비용 증가,오류의 잠재성 증대,처리 비용의 증대,설계 및 관리의 복잡성과 비용,불규칙한 응답 속도,통제의 어려움,데이터 무결성에 대한 위협 (전처리 필요) 의 단점이 있다. 테이블 요약(Summarization) 분산에는 동일한 테이블 구조에 동일한 내용의 데이터를 이용하여 통합된 데이터를 산출하는 분석요약, 분산되어 있는 다른 내용의 데이터를 이용하여 통합된 데이터를 산출하는 통합요약이 있다.

     

    SQLD강의 6주차는 크게 별 내용없었고 데이터베이스가 발열이 심하고 실제 로컬로 데이터베이스를 구축하는 것은 어렵기 때문에 주로 빌려쓴다. 그리고 SQLD는 Oracle DBMS에서 실습해야하는데 Oracle에서 교육용으로 무료로 할 수있도록 마련해둔 곳이 있다. 그것을 이용하면 된다 정도였던 것 같다.

     

    더보기

    SQL 코드카타 문제 푼 것들

    전체적으로 살짝 맞나 아닌가?하다가 해보니 맞네 또는 아니네 그럼 이거 바꿔보면 될려나? 맞네? 의 과정으로 풀었는 문제가 많아서 강의가 들어야하는 양이 많아 우선적으로 거기에 중점을 둬야할 것 같아서 SQL 코드 작성하는 감을 안 잃는 다는 느낌정도로만 우선 문제를 풀이하였다 아마 비슷한 애매한 사용들끼리 모아서 한번에 쓰임새를 확인하는 작업을 후에 해볼듯하다

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

    PRODUCT 테이블과 OFFLINE_SALE 테이블에서 상품코드 별 매출액(판매가 * 판매량) 합계를 출력하는 SQL문을 작성해주세요. 결과는 매출액을 기준으로 내림차순 정렬해주시고 매출액이 같다면 상품코드를 기준으로 오름차순 정렬해주세요. 라는 문제이다

    SELECT PRODUCT_CODE,
           PRICE*sum(SALES_AMOUNT) SALES
    from PRODUCT p inner join OFFLINE_SALE o on p.PRODUCT_ID=o.PRODUCT_ID
    group by 1
    order by 2 desc,1
    

    sum을 어디에 적어야할지 살짝 헷깔렸다 확인해볼려면테이블 전체 펼치고 대강 계산해보면서 감을 잡아야할 듯하다

     

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

    관리자의 실수로 일부 동물의 입양일이 잘못 입력되었습니다. 보호 시작일보다 입양일이 더 빠른 동물의 아이디와 이름을 조회하는 SQL문을 작성해주세요. 이때 결과는 보호 시작일이 빠른 순으로 조회해야합니다. 라는 문제였다

    SELECT ANIMAL_ID, NAME
    from ANIMAL_INS I inner join ANIMAL_OUTS O on i.ANIMAL_ID=o.ANIMAL_ID
    where i.DATETIME>o.DATETIME
    order by i.DATETIME
    

    처음에 이렇게 썼는데 animal_id랑 name에 어디꺼냐고 에러뜸

    SQL 실행 중 오류가 발생하였습니다.
    Column 'ANIMAL_ID' in field list is ambiguous
    
    SELECT i.ANIMAL_ID, i.NAME
    from ANIMAL_INS I inner join ANIMAL_OUTS O on i.ANIMAL_ID=o.ANIMAL_ID
    where i.DATETIME>o.DATETIME
    order by i.DATETIME
    

    아래처럼 수정해서 제출하니 문제없이 됬다

    아직 join중 어떤 join을 써야하는지 다른 것을 선택하여도 상관없는지에 대하여 확실히 null이 있을 것으로 예상되고 그것을 이용해야하는지 여부가 보인다면 확신이 서나 그렇지 않다고 생각되는 것들은 아직도 고민이 되며 헷깔린다.

     

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

    입양을 간 동물 중, 보호 기간이 가장 길었던 동물 두 마리의 아이디와 이름을 조회하는 SQL문을 작성해주세요. 이때 결과는 보호 기간이 긴 순으로 조회해야 합니다.라는 문제이다

    SELECT o.ANIMAL_ID,o.NAME
    from ANIMAL_INS i left join ANIMAL_OUTS o on i.ANIMAL_ID=o.ANIMAL_ID
    where o.ANIMAL_ID is not null
    order by (o.DATETIME-i.DATETIME) desc
    limit 2
    

     

     이 문제는 입양 안 간 동물도 있을 것이고, 입양 간 동물에 한해서 계산을 통해 결과를 도출해야하기에 망설임없이 바로 문제를 풀었다. 하지만 너무 빠르게 풀고 끝내서 그런지 정렬기준이 다른 방식도 있는지 더 좋은 방식이 있는지 등에 대하여는 생각해보지 않아서 후에 한번 더 확인해보는 것이 좋을 듯하다.

     

     

    더보기

    체육복 문제 (python 코드카타) , 리스트 원소제거

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

    대강 체육복이 있고 여분 1개씩 있는 학생이 있고, 도난 당해서 빌려 입어야하는 사람이 있고, 빌릴 수 있는 조건은 자기번호 +-1만 가능하다, 그리고 여분 가지고 있는 학생도 도난 당할 수 있는데 그럴 경우 자기가 자기옷 입어야해서 못빌려준다는 조건이 있다.

    def solution(n, lost, reserve):
        backup=0
        for i in range(len(lost)):
            if lost[i]-1 in reserve or lost[i]+1 in reserve:
                #lost.pop(i) #이것때문에 반복문에 문제가 생겨서 따로 카운트함
                #앞뒤로 둘다있다면 앞쪽부터 확인하고 있으니 앞쪽것을 사용
                if lost[i]-1 in reserve and lost[i]+1 in reserve:
                    reserve.remove(lost[i]-1)
                    backup+=1
                else:
                    if lost[i]-1 in reserve:
                        reserve.remove(lost[i]-1)
                        backup+=1
                    elif lost[i]+1 in reserve:
                        reserve.remove(lost[i]+1)
                        backup+=1
        return n-len(lost)+backup
    

    제일 처음에는 다른 친구에게 빌려서 해결된 인원에 대하여 리스트에서 제거하는 방식으로 생각하였는데, for문에서 그 리스트에 관련하여 돌리고 있었기에 문제가 생겨 for문을 그 리스트의 길이를 이용하여 새로운 리스트를 만드는 방식으로 해결했지만, 그 뒤에, for문은 i에 따라서 0,1…순서대로 돌아가는데 리스트의 원소를 제거하여 변경 사항이 생기니 lost에 없는 인덱스도 체크하게 되는 셈이 되어버려 index문제가 발생하였다.(IndexError: list index out of range) 따라서 그 부분을 제거하고 lost리스트는 그대로 두는대신 빌려준 횟수만큼 backup으로 체크하여 답을 보완하였는데 제출평가를 받아보니 실패가 몇 건 있었다 의아해서 살펴보니 규칙이 비교적 간단하다 생각하여 대강 읽다가 가장 아래부분을 빠트렸는데, 여벌이 있는 학생도 도난당하는 것이 가능하다 단, 하나만 도난 당한다고 가정하며 이 경우는 자기 남은 것을 입어야하기에 다른 사람이게 빌려줄 수 없다고 되어있다(솔직히 다른사람꺼 빌리고 자기꺼 빌려줄 수 있으면 상관없지않나.. 그랬으면 원래 코드도 문제 없이 될텐데.. )째든 제한사항이니 적용해보면

    def solution(n, lost, reserve):
        backup=0
        #여분있는 학생이 도난됬을 경우 적용하여 업데이트할 임시 저장리스트
        lost_update=[]
        for i in lost:
            if i not in reserve:
                lost_update.append(i)
            else: #reserve도 거기 맞게 업데이트
                reserve.remove(i)
        lost=lost_update
        lost.sort()
        #따로 언급이 없었고, 예시에서는 전부 정렬된 리스트로 줘서 생각 안했는데
        #정렬 안된 것에 대해서도 처리를 해줘야 했었나봄
        for i in range(len(lost)):
            if lost[i]-1 in reserve or lost[i]+1 in reserve:
                #lost.pop(i) #이것때문에 반복문에 문제가 생겨서 따로 카운트함
                #앞뒤로 둘다있다면 앞쪽부터 확인하고 있으니 앞쪽것을 사용
                if lost[i]-1 in reserve and lost[i]+1 in reserve:
                    reserve.remove(lost[i]-1)
                    backup+=1
                else:
                    if lost[i]-1 in reserve:
                        reserve.remove(lost[i]-1)
                        backup+=1
                    elif lost[i]+1 in reserve:
                        reserve.remove(lost[i]+1)
                        backup+=1
        return n-len(lost)+backup
    

    처음에는 lost를 정렬해주지 않았는데 실패한 케이스가 있어서 질문하기를 살펴보니 sort를 쓰니 해결되었다고 해서 해보니 해결되었다. 아마 따로 언급이 없었고, 예시에서는 전부 정렬된 리스트로 줘서 생각 안 했는데 정렬 안된 것에 대해서도 처리를 해줘야 했었나 보다

     

    그리고 초반에 원소 제거할 때 어느 방법이 가장 빠르고 리소스 적게 드는지 궁금해 chatGPT에게 물어보니 상황마다 효율이 다르며 성능 측정을 원한다면 timeit이라는 모듈을 사용해서 실제 테스트해볼 수 도 있다고 한다. 어제 찾은 프로파일링 도구라는 것과 같이 활용해서 성능테스트를 해볼 수 있을듯 하다.

    https://chat.openai.com/share/43935bfc-e56e-4519-b7f3-8b1903b4a739

     

     

    더보기

    문자열나누기(python 코드카타)

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

    def solution(s):
        answer = 0
        same_str=''
        same_num=0
        other_num=0
        for i in range(len(s)):
            if same_num==0: #같은 문자로 체크할 문자 저장
                same_str=s[i]
                same_num+=1
            elif same_str==s[i]:
                same_num+=1
            else: #세고 있는 글자가 있고 다른문자가 나올경우
                other_num+=1
                if same_num==other_num: #세고있던 글자와 다른글자 수가 같아질 경우
                    answer+=1 #문자열을 한번 나눠준다(실제로는 안하고 횟수만 체크)
                    same_num=0 #그리고 다시 세던횟수는 초기화
                    other_num=0
            if i==len(s)-1 and same_num!=other_num: #마지막 것인지 체크
                answer+=1
        return answer
    
    #시각화 해서 체크 편하기용
    '''def solution(s):
        answer = 0
        same_str=''
        split_str='' #시각적 체크용 나중에 삭제
        same_num=0
        other_num=0
        for i in range(len(s)):
            if same_num==0: #같은 문자로 체크할 문자 저장
                same_str=s[i]
                same_num+=1
                split_str=''
            elif same_str==s[i]:
                same_num+=1
            else: #세고 있는 글자가 있고 다른문자가 나올경우 아마 마지막꼬다리가 문제될수도
                other_num+=1
                if same_num==other_num: #세고있던 글자와 다른글자 수가 같아질 경우
                    answer+=1 #문자열을 한번 나눠준다(실제로는 안하고 횟수만 체크)
                    same_num=0 #그리고 다시 세던횟수는 초기화
                    other_num=0
            if i==len(s)-1 and same_num!=other_num: #마지막 것인지 체크
                answer+=1
            split_str+=s[i]
            print(answer,split_str,same_str,same_num,other_num)
        return answer'''
    

    뭔가 느낌이 나중에 비슷하게 응용할 수 있는 문제가 나올 것 같아 기록해둠

    이번에도 처음 시도는 for i in s 자체를 하고 싶었는데 아래 마지막 꼬다리 부분을 처리하는 부분에서 i==s[-1] 이런 식으로 하니 같은 문자가 여러 개 있다면 조건이 여러 번 충족되서 문제가 발생하였기 때문에 확실히 구별하기 위해서 for i in range(len(s))로 바꿔서 사용했는데 번거롭더라도 세세한 지칭이 가능해서 아무래도 for i in range(len(s))방식을 많이 쓰게 되는 것 같다.

     

    추가 여담으로 7주차 강의는 다 들었지만 실습부분이 꽤 있었는데 아직 내용 체크 및 대략적인 정리도 제대로 못한 상태인데, 오늘은 너무 피곤한 관계로 내일 마저 내용 확인하고 정리하여 작성할 생각이다.

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

    2023-12-30~2023-01-01  (0) 2024.01.02
    2023-12-29  (1) 2023.12.29
    2023-12-27  (0) 2023.12.27
    2023-12-26  (1) 2023.12.27
    2023-12-23  (0) 2023.12.23
Designed by Tistory.