2015-03-06 2 views
-1

У меня есть таблица SQL Server, которая имеет столбец XML, который имеет данные, как показано ниже. В таблице будет несколько записей. Скажем, таблица T1 и столбец C1.SQL XML Parsing в T-SQL

Наше требование - нам нужно получить последние данные (по максимальному датированному датированному датированному XML узлу XML для отдельных разделов, таких как AAA, BB, CC).

<XMLDoc> 
    <AAA> 
     <Name>Name_A</Name> 
     <Value>Val_A</Value> 
     <dateReported>1/1/2001</dateReported> 
    </AAA> 
    <AAA> 
     <Name>Name_B</Name> 
     <Value>Val_B</Value> 
     <dateReported>1/1/2014</dateReported> 
    </AAA> 
    <AAA> 
     <Name>Name_C</Name> 
     <Value>Val_C</Value> 
     <dateReported>1/1/2012</dateReported> 
    </AAA> 
    <AAA> 
     <Name>Name_D</Name> 
     <Value>Val_D</Value> 
     <dateReported>1/1/2011</dateReported> 
    </AAA> 
    <BB> 
     <ID>112</ID> 
     <dateCreated>1/1/2011</dateCreated> 

    </BB> 
     <BB> 
     <ID>121</ID> 
     <dateCreated>1/1/2012</dateCreated> 
    </BB> 
    <BB> 
     <ID>12</ID> 
     <dateCreated>1/1/2015</dateCreated> 
    </BB> 
    <CC> 
     <Type>XML</Type> 
     <dateUpdated>1/1/2015</dateCreated> 
    </CC> 
    <CC> 
     <Type>TXT</Type> 
     <dateUpdated>3/3/2015</dateUpdated> 
    </CC> 
    <CC> 
     <Type>XLS</Type> 
     <dateUpdated>2/2/2015</dateUpdated> 
    </CC> 
</XMLDoc> 

У меня есть SQL написано ниже

SELECT 
     ID, 
     Name = C1.value('(/XMLDoc/AAA/Name)[1]', 'varchar(100)'), 
     Value = C1.value('(/XMLDoc/AAA/Value)[1]', 'varchar(100)'), 
     BB_ID = C1.value('(/XMLDoc/BB/ID)[1]', 'int'), 
     CC_Type = C1.value('(/XMLDoc/CC/Type)[1]', 'varchar(50)') 
From T1 

Нам нужен результат, как

Id Name, Value, BB_ID, CC_Type 
1 Name_B Val_B 12 TXT 

нужны ваши входы

ответ

0

У меня есть поиск в Интернет и найти хороший способ справиться с макс:

Это таблица я использовал: CREATE TABLE #xmlTable (ID INT, xmlData XML)

Выбрать:

SELECT 
    ID 
    , xmlData.value ('(/XMLDoc/AAA[not(/XMLDoc/AAA/dateReported > dateReported)]/Name)[1]', 'varchar(100)') AS Name 
    , xmlData.value ('(/XMLDoc/AAA[not(/XMLDoc/AAA/dateReported > dateReported)]/Value)[1]', 'varchar(100)') AS Value 
    , xmlData.value ('(/XMLDoc/BB[not(/XMLDoc/BB/dateCreated > dateCreated)]/ID)[1]', 'INT') AS BB_ID 
    , xmlData.value ('(/XMLDoc/CC[not(/XMLDoc/CC/dateUpdated > dateUpdated)]/Type)[1]', 'varchar(50)') AS CC_Type 
FROM #xmlTable AS xt 

И, наконец, результат:

ID Name Value BB_ID CC_Type 
1 Name_B Val_B 121  TXT 

Решение, которое я нашел в этом примере https://stackoverflow.com/a/3786761/1692632

1

Ваш образец XML ужасно неправильно - много закрывающих тегов Арен» t действительно закрывающий тег, некоторые не соответствуют открывающим тегам, и есть </x> в th e в середине всего этого без каких-либо открывающих тегов ... в следующий раз, пожалуйста, постарайтесь убедиться, что вы публикуете действительно действительный XML!

Попробуйте с этим кодом:

DECLARE @T1 TABLE (ID INT NOT NULL, XmlContent XML) 

INSERT INTO @T1 VALUES(1, '<XMLDoc> 
    <AAA> 
     <Name>Name_A</Name> 
     <Value>Val_A</Value> 
     <dateReported>1/1/2001</dateReported> 
    </AAA> 
    <AAA> 
     <Name>Name_B</Name> 
     <Value>Val_B</Value> 
     <dateReported>1/1/2014</dateReported> 
    </AAA> 
    <AAA> 
     <Name>Name_C</Name> 
     <Value>Val_C</Value> 
     <dateReported>1/1/2012</dateReported> 
    </AAA> 
    <AAA> 
     <Name>Name_D</Name> 
     <Value>Val_D</Value> 
     <dateReported>1/1/2011</dateReported> 
    </AAA> 
    <BB> 
     <ID>112</ID> 
     <dateCreated>1/1/2011</dateCreated> 
    </BB> 
    <BB> 
     <ID>121</ID> 
     <dateCreated>1/1/2012</dateCreated> 
    </BB> 
    <BB> 
     <ID>12</ID> 
     <dateCreated>1/1/2015</dateCreated> 
    </BB> 
    <CC> 
     <Type>XML</Type> 
     <dateUpdated>1/1/2015</dateUpdated> 
    </CC> 
    <CC> 
     <Type>TXT</Type> 
     <dateUpdated>3/3/2015</dateUpdated> 
    </CC> 
    <CC> 
     <Type>XLS</Type> 
     <dateUpdated>2/2/2015</dateUpdated> 
    </CC> 
</XMLDoc>') 

;WITH XmlData AS 
(
    SELECT 
     ID, 
     NodeType = 'AAA', 
     RelevantDate = XC.value('(dateReported)[1]', 'datetime'), 
     Name = XC.value('(Name)[1]', 'varchar(50)'), 
     Value = XC.value('(Value)[1]', 'varchar(50)') 
    FROM 
     @T1 
    CROSS APPLY 
     XmlContent.nodes('/XMLDoc/AAA') XT(XC) 

    UNION 

    SELECT 
     ID, 
     NodeType = 'BB', 
     RelevantDate = XC.value('(dateCreated)[1]', 'datetime'), 
     Name = null, 
     Value = XC.value('(ID)[1]', 'varchar(50)') 
    FROM 
     @T1 
    CROSS APPLY 
     XmlContent.nodes('/XMLDoc/BB') XT(XC) 

    UNION 

    SELECT 
     ID, 
     NodeType = 'CC', 
     RelevantDate = XC.value('(dateUpdated)[1]', 'datetime'), 
     Name = XC.value('(Type)[1]', 'varchar(50)'), 
     Value = null 
    FROM 
     @T1 
    CROSS APPLY 
     XmlContent.nodes('/XMLDoc/CC') XT(XC) 
) 
SELECT 
    xd.ID, 
    Name = MAX(Name), 
    Value = MAX(Value), 
    BB_ID = MAX(BB_ID), 
    CC_Type = MAX(CC_Type) 
FROM 
    XmlData xd 
WHERE 
    xd.RelevantDate = (SELECT MAX(xd1.RelevantDate) FROM XmlData xd1 WHERE xd1.NodeType = xd.NodeType) 
GROUP BY 
    xd.ID 

Это дает мне выход:

enter image description here

В принципе, принимая ваш XML, я создаю CTE (Common Expression Table), что извлекает соответствующую информацию для каждого из «типов узлов» - узлов <AAA>, узлов <BB> и <CC>. Затем я могу получить MAX() для даты для каждой из этих групп, выбрав из этого CTE.

+0

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

+0

@Saravanan: обновил мой ответ - попробуйте еще раз –

+0

Спасибо, но этот запрос дает 3 строки, я хочу, чтобы результат был как один имя строки, значение, BB_ID, CC_Type 1 Name_B Val_B 12 TXT – Saravanan