상권's

TIL 35 관계형 데이터베이스 (2021.11.12) 본문

~2022 작성 글/TIL

TIL 35 관계형 데이터베이스 (2021.11.12)

라마치 2021. 11. 12. 17:58
-오늘의 코플릿 2021.11.12-
문제
세로와 가로의 길이가 각각 M, N인 방의 지도가 2차원 배열로 주어졌을 때, 1은 장애물을 의미하고 0 이동이 가능한 통로를 의미합니다. 로봇은 지도 위를 일분에 한 칸씩 상하좌우로 이동할 수 있습니다. 로봇의 위치와 목표 지점이 함께 주어질 경우, 로봇이 목표 지점까지 도달하는 데 걸리는 최소 시간을 리턴해야 합니다.
인자 2 : src number 타입을 요소로 갖는 배열
인자 3 : dst number 타입을 요소로 갖는 배열
//상 하 좌 우에 해당하는 움직임을 배열로 만든다
//출발지부터 시작해서 => 상 하 좌 우 배열을 돈다 undefined일 경우 return;
//undefined가 아닐 경우 count 1 제일 먼저 도착을 하는 게 있으면 바로 리턴한다.

첫 수도코드 => 수도코드대로 코드를 구현하는데 어려움이 있었습니다. 레프런스를 보니, 다른 거 같지만 수도코드랑 비슷한 거도 같아서 구현을 못했다는 점이 많이 아쉬웠습니다. 구조분해 할당을 생각 못해서 해당 부분에서 코드로 구현할 때, 애를 좀 먹었습니다. 구조분해할당을 수시로 생각을 하고, 자주 사용해보고 익숙해져야 할 거 같습니다.

그리고 count라는 변수를 만들어서 진행이 될 때마다 하나씩 올려준 다음에 해당 위치에 도달하면 배열 변수에 넣어주고, 이 부분의 제일 작은 수를 리턴을 하는 방향으로 구상을 했었습니다. 이 경우에는, 해당 위치와 현재의 위치가 동일한 지 여부를 확인하기 위한 부분이 배열끼리의 비교이기 때문에 참조주소가 달랐습니다.

const robotPath = function (room, src, dst) {

  const aux = (M, N, candi, step) => {
    const [row, col] = candi;// 구조분해 할당으로 변수에 값을 할당한다.
    if (row < 0 || row >= M || col < 0 || col >= N) return;  // M, N은 각각 열의 길이, 행의 길이를 의미한다.
    if (room[row][col] === 0 || room[row][col] > step) {
      // 0 일 경우에는, 갈 수 있는 길이라는 뜻이며,
      // step 보다 room[row][col] 값이 큰 경우는, 해당 위치로 오는데
      // 지금 가는 길 보다 더 돌아서 오는 길이기 때문에
      // 최소의 움직임으로 갈 수 있는 수를 찾기 위해서 step으로 바꿔준다.
      room[row][col] = step;
    } else {
      // 1일 경우는 가지 못하는 길이기 때문에 탈출
      // room[row][col] 이 더 작다면, 해당 방법은 그 위치로 가는데에
      // 기존의 방법보다 더 돌아가는 방법이기 때문에 탈출
      return;
    }
    aux(M, N, [row + 1, col], step + 1); // 상
    aux(M, N, [row - 1, col], step + 1); // 하
    aux(M, N, [row, col - 1], step + 1); // 좌
    aux(M, N, [row, col + 1], step + 1); // 우
  };

  aux(room.length, room[0].length, src, 1);

  const [r, c] = dst;
  return room[r][c] - 1; // step이 1부터 시작을 했기 때문에 1을 빼줘야 한다.
};

 


관계형 데이터베이스

구조화된 데이터는 하나의 테이블로 표현할 수 있습니다. 사전에 정의된 테이블을 relation 이라고도 부르기 때문에, 테이블을 사용하는 데이터베이스를 관계형 데이터베이스(Relational database)라고 합니다.

 

관계형 데이터베이스 키워드

  • 데이터(data): 각 항목에 저장되는 값입니다.
  • 테이블(table; 또는 relation) : 사전에 정의된 열의 데이터 타입대로 작성된 데이터가 행으로 축적됩니다.
  • 칼럼(column; 또는 field) : 테이블의 한 열을 가리킵니다.
  • 레코드(record; 또는 tuple) : 테이블의 한 행에 저장된 데이터입니다.
  • 키(key) : 테이블의 각 레코드를 구분할 수 있는 값입니다. 각 레코드마다 고유한 값을 가집니다. 기본키(primary key)와 외래키(foreign key) 등이 있습니다.

테이블 관계 종류

  • 1:1 관계
  • 1:N 관계
  • N:N 관계
  • self referencing 관계

1:1 관계

하나의 레코드가 다른 테이블의 레코드 한 개와 연결된 경우입니다.

각 전화번호가 단 한 명의 유저와 연결되어 있고, 그 반대도 동일하다면, User 테이블과 Phonebook 테이블은 1:1 관계(One-to-one relationship)입니다.

 

그러나 1:1 관계는 자주 사용하지 않습니다. 1:1로 나타낼 수 있는 관계라면 User 테이블에 phone_id를 대신해 phone_number를 직접 저장하는 게 나을 수 있습니다.

 

1:N 관계

하나의 레코드가 서로 다른 여러 개의 레코드와 연결된 경우입니다.

이 구조에서는 한 명의 유저가 여러 전화번호를 가질 수 있습니다. 그러나 여러 명의 유저가 하나의 전화번호를 가질 수는 없습니다. 이런 1:N(일대다) 관계는 관계형 데이터베이스에서 가장 많이 사용합니다.

 

N:N 관계

여러 개의 레코드가 다른 테이블의 여러 개의 레코드와 관계가 있는 경우입니다. N:N(다대다) 관계를 위해 스키마를 디자인할 때에는, Join 테이블을 만들어 관리합니다. 1:N(일대다) 관계와 비슷하지만, 양방향에서 다수의 레코드를 가질 수 있습니다.

 

다음과 같이 여행 상품을 관리하는 테이블이 있다고 가정하겠습니다. 여러 개의 여행 상품이 있고, 여러 명의 고객이 있습니다. 고객 한 명은 여러 개의 여행 상품을 구매할 수 있고, 여행 상품 하나는 여러 명의 고객이 구매할 수 있습니다.

다대다 관계는 두 개의 일대다 관계와 그 모양이 같습니다. 두 개의 테이블과 1:N(일대다) 관계를 형성하는 새로운 테이블로 N:N(다대다) 관계를 나타낼 수 있습니다.

 

이렇게 다대다 관계를 위한 테이블을 조인 테이블이라고 합니다.

customer_package 테이블에서는 고객 한 명이 여러 개의 여행 상품을 가질 수 있고, 여행 상품 하나를 여러 명의 고객이 가질 수 있습니다.

 

customer_package 테이블은 customer_id와 package_id를 묶어주는 역할입니다. 이 테이블을 통해 어떤 고객이 몇 개의 여행 상품을 구매했는지 또는, 어떤 여행 상품이 몇 명의 고객을 가지고 있는지 등을 확인할 수 있습니다. 이렇게 조인 테이블을 생성하더라도, 조인 테이블을 위한 기본키(여기서는 cp_id)는 반드시 있어야 합니다.

 

자기참조 관계(Self Referencing Relationship)

때로는 테이블 내에서도 관계가 필요합니다. 예를 들어 추천인이 누구인지 파악하기 위해 사용할 수 있습니다.

다음과 같이 유저 테이블이 있습니다. user_id는 기본 키(primary key), name은 사용자의 이름, 그리고 recommend_id는 추천인 아이디입니다.

User 테이블의 recommend_id는 User 테이블의 user_id와 연결되어 있습니다. 한 명의 유저(user_id)는 한 명의 추천인(recommend_id)를 가질 수 있습니다. 그러나 여러 명이 한 명의 유저를 추천인으로 등록할 수 있습니다. 이 관계는 1:N(일대다) 관계와 유사하다고 생각할 수 있습니다. 그러나 일반적으로 일대다 관계는 서로 다른 테이블의 관계를 나타낼 때 표현하는 방법입니다.

Comments