2014-08-29 6 views
0

У меня есть набор таблиц (с несколькими отношениями один-много), которые образуют единую «единицу». Мне нужно обеспечить, чтобы мы отсеивали дубликаты, но для определения дубликатов требуется рассмотрение всех данных.Идентифицировать повторяющиеся узлы Xml

Чтобы ухудшить ситуацию, рассматриваемая БД все еще находится в режиме совместимости 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 - A Unit узла (содержащий данные блока, и условие суб-коллекция) является уникальным, если нет других 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 

Но вопрос у меня есть, что я не может показаться, что XML для каждого модуля будет отображаться в виде новой записи, и я не уверен, как сравнить узлы блоков для поиска дубликатов.

Как я могу запустить этот запрос, чтобы определить, есть ли дубликаты узлов Xml Unit в коллекции?

+0

Можете ли вы добавить свой желаемый результат? – Tanner

+0

Будет делать, хотя выходного формата я не так суетился, пока я могу сравнить две единицы и идентифицировать уникальность - будь то одна строка со всеми значениями или большая таблица со всеми столбцами для всех объединенных строк, Я не против. –

+0

Это хорошо, но на основе результатов, которые генерирует ваша скрипка, я не уверен, как вы определяете уникальность, поэтому, если вы можете использовать то, что должно выглядеть на выходе, вы можете получить дополнительную помощь в создании этого вывода. – Tanner

ответ

0

Таким образом, мне удалось выяснить, что Мне нужно было это сделать. Это немного неуклюже.

Во-первых, вам нужно обернуть оператор Xml Select в другой выбор в отношении таблицы Unit, чтобы убедиться, что мы закончили с 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, то Индентификационный дубликат.

+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 
Смежные вопросы