C.W.K.
Stream
Lesson 06 of 10 · published

Cardinality — 1:N 과 N:N

~14 min · relationships, cardinality, junction-table

Level 0Scout
0 XP0/80 lessons0/10 achievements
0/120 XP to next level120 XP to go0% complete

99% 모델링하는 두 관계

거의 모든 관계형 schema 가 두 cardinality 위에 세워져:

  • One-to-many — author 한 명에 post 여러 개. 'many' 쪽에 FK.
  • Many-to-many — post 마다 tag 여러 개, tag 마다 post 여러 개. Junction 테이블 (join table, link table, association table) 로 구현.

1:1 은 드물어 — 보통 두 테이블 합치라는 신호, hot/cold 컬럼 의도적 분리 빼고.

Principle: TEXT 컬럼에 comma-separated id list 넣고 싶어지면 멈춰. 그게 junction 테이블이 비명 지르는 거. SQL 은 '이 컬럼에 42 들어있는 row 다 찾기' 답이 안 좋고, junction 테이블이 그걸 인덱싱된 JOIN 으로 바꿔.

Code

1:N — author + post·sql
CREATE TABLE authors (
  id INTEGER PRIMARY KEY, name TEXT NOT NULL
) STRICT;

CREATE TABLE posts (
  id INTEGER PRIMARY KEY,
  author_id INTEGER NOT NULL REFERENCES authors(id),
  title TEXT NOT NULL
) STRICT;

CREATE INDEX idx_posts_author ON posts(author_id);  -- 거의 항상 원함
N:N — post + tag, junction 테이블·sql
CREATE TABLE tags (
  id INTEGER PRIMARY KEY, name TEXT NOT NULL UNIQUE
) STRICT;

CREATE TABLE post_tags (
  post_id INTEGER NOT NULL REFERENCES posts(id) ON DELETE CASCADE,
  tag_id  INTEGER NOT NULL REFERENCES tags(id)  ON DELETE CASCADE,
  PRIMARY KEY (post_id, tag_id)
) WITHOUT ROWID;

-- 'sql' 태그 달린 모든 post:
SELECT p.id, p.title FROM posts p
INNER JOIN post_tags pt ON pt.post_id = p.id
INNER JOIN tags t       ON t.id      = pt.tag_id
WHERE  t.name = 'sql';

External links

Exercise

N:N 디자인: user 가 post favorite. 3 테이블 (users, posts, favorites) 빌드, query 4 개: (1) 한 user 의 favorite post, (2) 한 post 를 favorite 한 user, (3) top-10 favorite post, (4) favorite 없는 user. 어디서 인덱스 필요했는지 기록.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.