2016-09-23 4 views
0

은 이제 사용자가이 같은 게시물 테이블이 있다고 가정 해 봅시다 : ID = 1저장 중복 필드 : 좋거나 나쁜

enter image description here

포스트는 사용자가 게시 한 첫 번째 게시물입니다. id = 2으로 게시 - 게시물에 작성된 수정이며 id = 3 - 게시물의 최신 최신 버전입니다. 을 USER_ID로

post_param_a뿐만 아니라, 버전을 통해 변경할 수 없습니다 - 그들은 항상 첫 번째 버전 이후 동일하게 유지. 그래서 우리는이처럼 저장할 수 :

enter image description here

그래서 질문은 다음과 같습니다 가 그것에게 두 번째 방법을 저장하기 위해 더 나은 것, 아니 중복으로? 이렇게하면 현재 버전의 사용자 게시물을 얻으려면 첫 번째 버전에 가입하고 user_id을 항상 확인해야합니다. 아니면이 경우 중복 된 필드를 저장해도됩니까?

p.s. 한 곳에서 그들 모두를 저장하는 우리가 버전을 통해 변경할 수 없습니다 값의 중복과 사고의 변화를 피하기 위해 원하기 때문에이 의문을 제기한다, 그래서 우리는 원하는

+1

거버는 # 2를 수행합니다. – Drew

+0

# 1은 어쨌든 비정규 화됩니다. – Drew

+0

@Drew 그래서 가장 좋은 방법은 무엇입니까? 별도의 테이블로 분리 하시겠습니까? –

답변

1

엔티티 Post을 가지고 간단한 튜플 볼이 완벽하게 정규화

ID User_ID Post_Param_A Comment 
1  69   foo This is a post 

. 그러나 게시물이 편집을 거쳐 변경 사항을 추적하려고합니다. 그래서 다른 필드를 추가하여 변경 사항을 추적합니다. 그러나 증분 값 대신 datetime 필드를 추가하는 것이 좋습니다.

ID EffDate  User_ID Post_Param_A Comment 
1 1/1/16 12:00  69   foo This is a post 

이 두 가지 장점이 있습니다 변경 사항을 추적 할 경우이 버전이 저장 될 때 1), 어쨌든 알고 싶은 것, 2) 당신이 게시물을 찾기위한 가장 큰 증분 값을 찾을 필요는 없습니다 각 새 버전을 저장할 값을 지정하십시오. 현재 날짜와 시간 만 저장하면됩니다.

그러나 증분 값 또는 날짜가 있으면 문제가 발생합니다. 간단한 행에서 각 필드는 PK에 대한 함수 종속성을가집니다. 버전 행에서 User_ID 및 Post_Param_A는 PK에 대한 종속성을 유지하지만 Comment는 이제 PK EffDate에 종속됩니다.

튜플은 더 이상 2nf가 아닙니다.

그래서 용액을 정규화하는 간단한 문제이다 함께

ID User_ID Post_Param_A 
1  69   foo 

ID EffDate  Comment 
1 1/1/16 12:00 This is a post 
1 1/1/17 12:00 An edit was made 
1 1/1/17 15:00 The last and current version (so far) 

(ID, EffDate) 새로운 테이블의 복합 PK.

쿼리 최신 게시물을 읽을 수는 조금 복잡하다 :

select p.ID, v.EffDate, p.User_ID, p.Post_Param_A, v.Comment 
    from Posts p 
    join PostVersions v 
    on v.ID = p.ID 
    and v.EffDate = (
     select Max(v1.EffDate) 
      from PostVersions v1 
     where v1.ID = p.ID 
      and v1.EffDate <= today) 
    and p.ID = 1; 

이 보이는하고 인상적으로 빠른처럼 복잡 정말 아니다. 정말로 깔끔한 특징은 - "오늘"을 1/1/17 13:00과 바꾸면 결과가 두 번째 버전이됩니다. 따라서 동일한 쿼리를 사용하여 현재 또는 과거를 쿼리 할 수 ​​있습니다.

마지막 줄 ("및 p.ID = 1")이 제거 된 상태에서 "오늘"쿼리의보기를 만들어 또 다른 멋진 기능을 얻을 수 있습니다. 이보기는 모든 게시물의 최신 버전을 표시합니다. 뷰에 트리거를 작성하면 현재 버전에만 관심이있는 앱이 기본 구조를 고려하지 않고 작업을 수행 할 수 있습니다.

1

각의 post_param_a를 저장하는 경우 당신은 별도의 테이블을 가질 수 post_id이면 NULL 값이나 중복 값이 ​​필요하지 않습니다.

0

user_idpost_id과 정렬되어 다양한 해석을 피하기 때문에 더 좋습니다.

이 방법으로 현재 사용자 버전의 게시물을 얻으려면 첫 번째 버전에 가입하고 user_id를 항상 확인해야합니다.

언제든지 게시물의 마지막 버전을 얻을 수 있도록 timestamp 필드 추가에 대해 생각하십니까?

에서 NULL은 데이터가 커질 때 모호 할 수 있습니다. 심지어 쿼리하는 것조차 어렵습니다. 모든 SQL은 NULL 사례와 그 구체적인 의미에 대해 생각하도록 설계되어야합니다.

세 번째 해결은 두 개의 분리 된 테이블을 사용하여 테이블을 정규화 할 수 있습니다. postpost_history. post_param_a은 버전 전체에서 변경 될 수없고 user_id과 같이 변경 될 수 없다는 질문에서 언급했듯이 첫 번째 버전 이후로 항상 동일하게 유지됩니다. 이 경우,

  • 테이블 post에서는 (변경되지 않습니다) 영구적 게시물에 관련된 정보를 저장할 수 있습니다 : id, param_a, user_id, created_at을 ...테이블 post_history에서
  • , 각 버전/수정 관련된 게시물에 관련된 정보 저장할 수 있습니다 : version_id, comment, modified_at을 ... 그리고 당신은 post_history.post_id = post.id
을 나타내는 두 번째 테이블의 FK 제약 조건을 추가 할 수 있습니다