2013-03-19 2 views
0

정규화 된 테이블을 비정규 화하는 방법에 대해 조언하는 사람이 있습니까? 나는 인터넷 검색에도 불구하고 그것에 많이 찾을 수 없었어요.완전히 정규화 된 테이블을 비정규 화합니다.

레코드가 업데이트 될 때마다 (삽입되지는 않지만 현재는 걱정할 필요가 없음) TableA에서 레코드가 변경된 필드의 값과 레코드가 수행되었을 때 관련된 타임 스탬프와 함께 HistoryOfTableA에 삽입됩니다.

예 :

TableA의 필드 :

TableA_Id, FieldA, FieldB, FieldC, FieldD.... etc 

HistoryOfTableA 기록 :

HistID, TableA_Id, FieldChanged, OldValue, NewValue, DateCreated 
1, 1, 'FieldA', 1, 2, <2013-03-18 12:20:00> 
2, 1, 'FieldB', A, B, <2013-03-18 12:20:00> 
3, 1, 'FieldC', A, B, <2013-03-18 12:20:00> 

이 상황은 내가보고 목적을위한 몇 가지 SQL을 만들 찾고있다. 그래서 나는 특정 시점을 지정할 수 있기를 원하고, 그 병목 테이블 엔트리를 모아서 TableA로부터 그 레코드의 상태가 그 때 무엇인지 알아낼 수 있어야합니다.

것은 내가 역사 테이블을 기반으로 테이블을 만들 수 있습니다 생각하고 만든 날짜와 테이블에서 이드

예에 합류하고있다.

select HistA.NewValue, 
     HistB.NewValue, 
     .... 
from FieldA_HistoryOfTableA HistA 
    inner join FieldB_HistoryOfTableA HistB on HistA.DateCreated = HistB.DateCreated 
     and HistA.TableA_Id = HistB.TableA_Id 
    inner join ... etc 
where HistA.FieldChanged = 'FieldA' 
and HistB.FieldChanged = 'FieldB' 
and .... etc... 

는하지만이 나에게 내가 원하는 모든 것을 제공하는 것입니다 생각하지 않는다 나는 SQL에서 순수하게이 작업을 수행 할 수 없습니다. 제쳐두고 TableA에는 20 개의 필드가 있으므로 20 개의 테이블을 조인하려는 것은 현명하지 않을 수 있습니다.

+0

어떤 DBMS를 사용하고 있습니까? –

+0

SQL Server 2005 – atamata

답변

-1

TableA에서 XML 열을 사용하여 TableA의 모든 행의 내역을 기록 할 수 있습니다. 즉, 모든 행에는 XML 형식의 열이 있으며 해당 행의 기록이 기록됩니다. 그런 다음 행 수가 많으면 행을 응용 프로그램에 끌어다 놓을 수 있으며 표 A의 각 레코드의 내역을 확인할 수 있습니다.

+1

이것은 좋지 않은 생각입니다. 열을 XML로 저장하여 기록을 저장 하시겠습니까? 업데이트가 어떻게 생겼겠습니까? –

+0

안녕하세요 Daniel, 모든 업데이트 저장 프로 시저에서 1) 업데이트가 발생하기 전에 레코드의 스냅 샷을 찍거나 2) 변경 될 필드 만 기록합니다. 변경 될 필드를 업데이트하는 동안 알 수 있기 때문입니다. 왜 이것이 나쁜 생각인지 자세히 설명해 주시겠습니까? – guruprasath

+0

모든 업데이트마다 (1) XML을 구문 분석하고, (2) 새 기록을 추가하고 (3) XML을 유지해야합니다. 게다가, 이제 SQL을 통해 그 역사가 더 이상 접근 가능하지 않습니다. –

2

문제는 표가 표준화 된 것이 아니라 그렇지 않습니다.

한 테이블의 필드로 식별되는 데이터는 다른 테이블의 데이터로 식별되므로 쿼리가 매우 복잡해집니다.

완전히 정규화 된 버전은 별도의 테이블에 TableA에서 필드를 저장하는 것입니다 :

TableA 
------------ 
TableA_Id 

TableAFields 
------------- 
TableA_Id 
FieldId 
Value 

Field 
--------- 
FieldId 
FieldName 

HistoryOfTableA 
---------------- 
TableA_Id 
FieldId 
OldValue 
ChangedDate 

이제 역사 테이블에서 필드에 가입 할 수 있습니다. 조금 까다 롭지 만 적어도 조인은 20 개가되지 않습니다. 당신은 하나의 기록으로, 당신이해야 하나 피벗이 원하는 경우

select ht.* 
from (select ht.*, 
      ROW_NUMBER() over (partition by FieldChanged, TableA_Id order by DateCreated desc) as seqnum 
     from HistoryOfTableA ht 
     where datecreated <= YOURDATEHERE 
    ) ht 
where seqnum = 1 

또는 집계를 수행하면 역사 테이블에서 가장 최근의 기록을 원하는 경우

+0

흠 네, 불행하게도 저는 스키마를 변경할 자유가 없습니다. – atamata

+0

@atamata : 알다시피, 나는 당신이 그것을 할 수 있다고 생각했다. 왜냐하면 그것이 당신이 테이블을 비정규화할 때 당신이하는 일이기 때문이다. 그렇다면 당신은 복잡한 길을 가고 있습니다 ... 최소한 복잡하게 만드는 부분은 알고 있습니다. – Guffa

1

, 다음과 같은 SQL을 사용할 수 있습니다. 후자의 방법이 있습니다 :

select ht.TableA_id, 
     max(case when FieldName = 'FieldA' then NewValue end) as FieldA, 
     . . . 
from (select ht.*, 
      ROW_NUMBER() over (partition by FieldChanged, TableA_Id order by DateCreated desc) as seqnum 
     from HistoryOfTableA ht 
     where datecreated <= YOURDATEHERE 
    ) ht 
where seqnum = 1 
group by TableA_id 
+0

고마워, 그게 도움이되고 내가 실제로 다른 보고서에 쓸거야. – atamata