2014-08-29 5 views
0

하나의 "단위"를 구성하는 일련의 테이블 (여러 개의 일 대 관계가 있음)이 있습니다. 나는 중복을 제거 할 필요가 있지만, 중복을 결정하려면 모든 데이터를 고려해야한다.중복 된 XML 노드 식별

문제가되는 DB는 여전히 SQL 2000 호환 모드이므로 더 이상 새로운 기능을 사용할 수 없습니다.

Create Table UnitType 
(
    Id int IDENTITY Primary Key, 
    Action int not null, 
    TriggerType varchar(25) not null 
) 

Create Table Unit 
(
    Id int IDENTITY Primary Key, 
    TypeId int Not Null, 
    Message varchar(100), 
    Constraint FK_Unit_Type Foreign Key (TypeId) References UnitType(Id) 
) 

Create Table Item 
(
    Id int IDENTITY Primary Key, 
    QuestionId int not null, 
    Sequence int not null 
) 

Create Table UnitCondition 
(
    Id int IDENTITY Primary Key, 
    UnitId int not null, 
    Value varchar(10), 
    ItemId int not null 
    Constraint FK_UnitCondition_Unit Foreign Key (UnitId) References Unit(Id), 
    Constraint FK_UnitCondition_Item Foreign Key (ItemId) References Item(Id) 
) 

Insert into Item (QuestionId, Sequence) 
Values (1, 1), 
(1, 2) 

Insert into UnitType(Action, TriggerType) 
Values (1, 'Changed') 

Insert into Unit (TypeId, Message) 
Values (1, 'Hello World'), 
(1, 'Hello World') 

Insert into UnitCondition(UnitId, Value, ItemId) 
Values (1, 'Test', 1), 
(1, 'Hello', 2), 
(2, 'Test', 1), 
(2, 'Hello', 2) 

나는이 문제의 간단한 양식을 보여주는 SqlFiddle을 만들었습니다.

이 유닛은 정확히 세세한 일치 결합하는 단위 의 모든 단위 (비-ID) 필드 및 모든 조건을 중복으로 간주된다. XML을처럼 고려 - 다른 Unit 노드가 그 정확한 문자열

Select 
    Action, 
    TriggerType, 
    U.TypeId, 
    U.Message, 
    (
     Select C.Value, C.ItemId, I.QuestionId, I.Sequence 
     From UnitCondition C 
     Inner Join Item I on C.ItemId = I.Id 
     Where C.UnitId = U.Id 
     For XML RAW('Condition') 
) as Conditions 
from UnitType T 
    Inner Join Unit U on T.Id = U.TypeId 
For XML RAW ('Unit'), ELEMENTS 

복사입니다 존재하지하지만이 문제가 I 있다는 것입니다 경우 Unit 노드 (단위 정보를 포함하고, 조건 하위 컬렉션) 고유 각 유닛이 새로운 레코드로 나타나게하는 XML을 얻지 못하는 것 같습니다. 중복을 찾기 위해 유닛 노드를 비교하는 방법을 모르겠습니다.

어떻게이 쿼리를 실행하여 컬렉션에 중복 노드 X이 있는지 확인할 수 있습니까?

+0

원하는 출력을 추가 할 수 있습니까? – Tanner

+0

출력 형식은별로 다르지 않지만 두 단위를 비교하고 고유성을 식별 할 수 있다면 모든 값을 가진 단일 문자열이든 모든 행이 결합 된 모든 열이 포함 된 큰 테이블 이건간에, 나는 상관하지 않는다. –

+0

괜찮 았지 만 귀사의 산출물을 기반으로 고유성을 식별하는 방법이 확실하지 않으므로 공예품을 출력 할 수 있다면 출력을 생성하는 데 도움이 될 수 있습니다. – Tanner

답변

0

그래서 아마도 시작, 내가 알아 내기 위해 관리 어떻게 나는해야했다. 그래도 좀 어색해.

먼저 Unit 테이블에 대해 xml Select 문을 다른 선택 영역으로 래핑하여 xml이 해당 단위만을 나타내는 지 확인해야합니다.

Select 
Id, 
(
    Select 
    Action, 
    TriggerType, 
    IU.TypeId, 
    IU.Message, 
    (
     Select C.Value, I.QuestionId, I.Sequence 
     From UnitCondition C 
      Inner Join Item I on C.ItemId = I.Id 
     Where C.UnitId = IU.Id 
     Order by C.Value, I.QuestionId, I.Sequence 
     For XML RAW('Condition'), TYPE 
    ) as Conditions 
    from UnitType T 
    Inner Join Unit IU on T.Id = IU.TypeId 
    WHERE IU.Id = U.Id 
    For XML RAW ('Unit') 
) 
From Unit U 

그런 다음이 내용을 다른 선택 항목으로 묶고 내용별로 XML을 그룹화 할 수 있습니다.

Select content, count(*) as cnt 
From 
    (
    Select 
     Id, 
     (
     Select 
      Action, 
      TriggerType, 
      IU.TypeId, 
      IU.Message, 
      (
       Select C.Value, C.ItemId, I.QuestionId, I.Sequence 
       From UnitCondition C 
       Inner Join Item I on C.ItemId = I.Id 
       Where C.UnitId = IU.Id 
       Order by C.Value, I.QuestionId, I.Sequence 
       For XML RAW('Condition'), TYPE 
     ) as Conditions 
     from UnitType T 
      Inner Join Unit IU on T.Id = IU.TypeId 
     WHERE IU.Id = U.Id 
     For XML RAW ('Unit') 
    ) as content 
    From Unit U 
) as data 
group by content 
having count(*) > 1 

이렇게하면 전체 콘텐츠가 동일한 전체 단위를 그룹화 할 수 있습니다.

"주목할 가치가있는 것"중 하나는 "고유성"을 테스트하는 것이고, 내부 XML 선택의 데이터가 항상 동일 함을 보장해야한다는 것입니다. 따라서 일관성을 유지하려면 관련 데이터 (예 : XML의 데이터)에 대한 주문을 적용해야합니다. 두 개의 동일한 콜렉션이 동일한 순서로 출력되는 한, 적용하는 순서는 중요하지 않습니다.

0

레코드가 중복되는지 여부를 확인하려면 모든 값을 하나의 문자열로 결합 할 필요가 없습니다. 이 같은 ROW_NUMBER 기능이 작업을 수행 할 수 있습니다

SELECT 
    Action, 
    TriggerType, 
    U.Id, 
    U.TypeId, 
    U.Message, 
    C.Value, 
    I.QuestionId, 
    I.Sequence, 
    ROW_NUMBER() OVER (PARTITION BY <LIST OF FIELD THAT SHOULD BE UNIQUE> 
         ORDER BY <LIST OF FIELDS>) as DupeNumber 
FROM UnitType T 
    Inner Join Unit U on T.Id = U.TypeId 
    Inner Join UnitCondition C on U.Id = C.UnitId 
    Inner Join Item I on C.ItemId = I.Id; 

DupeNumber이 1보다 큰 경우, ID를 중복을 기록합니다. 확실하지 - -

+0

그게 실제로 작동하지 않을 것입니다. 상황에 따라 다양한 양의 레코드가 있습니다. 그렇습니까? 전체 단위가 고유 한 것이지 그 안에있는 특정 레코드가 아닌지를 알아야합니다. –

+0

"다양한 양의 레코드"는 무엇을 의미합니까? 목록에는 기본 키를 나타내는 필드 만 포함됩니다. – Bulat

+0

단위는 여러 개의 UnitCondition 레코드를 가질 수 있습니다. 고유 한 컬렉션이 필요합니다. 여러 유닛은 동일한 레코드를 가질 수 있지만 유닛의 모든 레코드에 대해 모든 점에서 동일하지 않아야합니다. –

0

당신에 최종 답변이 구축하는 방법을
이것은이 고유하지 쌍을 찾을 것
을 시도해하지만

select u1.id, u2.id 
    from unit as u1 
    join unit as u2 
    on ui.ID < u2.id 
    join UnitCondition uc1 
    on uc1.unitID = u1.ID 
    full outer join uc2 
    on uc2.unitID = u2.ID 
    and uc2.itemID = uc1.itemID 
where uc2.itemID is null or uc1.itemID is null