2015-03-02 88 views
1

我有一个像下面SQL XML列过滤器基于XML节点聚合函数

<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></x> 
    <BB><ID>12</ID><BB> 
    <CC><Type>XML</Type></CC> 
</XMLDoc> 

我需要获取名称和值节点dateReported的最大XML列。到目前为止,我的SQL是像下面

SELECT 
    Col1 = Col.value('(/XMLDoc/x/AAA/Name)[1]', 'varchar(255)'), 
    Col2 = Col.value('(/XMLDoc/x/AAA/Value)[2]', 'varchar(255)'), 
    Col3 = Col.value('(/XMLDoc/BB/ID)[1]', 'varchar(255)'), 
    Col4 = Col.value('(/XMLDoc/CC/Type)[1]', 'varchar(255)') 
FROM 
    table t 

基本上我需要我的输出是Name_BVal_B12XML,因为datereported为AAA具有最大值。

+0

不是一个完整的解决方案,但是如果您使用了格式为yyyy-MM-dd的正确XML日期字符串(即, 2014-12-24)你可以用集合函数的XQuery语法,如max:'select Col.query('max(for $ d in/XMLDoc/AAA/dateReported return xs:date($ d))') FROM [Table]' – 2015-03-02 12:07:48

+0

假设日期字符串的格式正确,你能否给我解决我的解决方案的SQL – Saravanan 2015-03-02 13:00:38

回答

0

你可以尝试这样的事情 - 建立一个CTE(公共表表达式),以“提取”的XML值到关系格式,然后做一个简单的SELECT对结果集:

;WITH XmlCTE AS 
(
    SELECT 
     ID, 
     Name = XC.value('(Name)[1]', 'varchar(100)'), 
     Value = XC.value('(Value)[1]', 'varchar(100)'), 
     DateReported = XC.value('(dateReported)[1]', 'datetime') 
     BB_ID = YourXmlColumn.value('(/XMLDoc/BB/ID)[1]', 'int'), 
     CC_Type = YourXmlColumn.value('(/XMLDoc/CC/Type)[1]', 'varchar(50)') 
    FROM 
     dbo.YourTable 
    CROSS APPLY 
     YourXmlColumn.nodes('/XMLDoc/AAA') AS XT(XC) 
) 
SELECT * 
FROM XmlCTE 
WHERE DateReported = (SELECT MAX(DateReported) FROM XmlCTE) 
+0

谢谢Marc。但在我的查询中,我实际上从各种其他XML中选择意味着不同的行具有不同的XML(XPath将完全不同),在这种情况下,我将如何进行交叉应用。 – Saravanan 2015-03-02 11:51:08

+0

@Saravanan:更新了我的回复,包括您的''和''元素 – 2015-03-02 12:16:06

0

SQL XML query可以在这种情况下

with cte as (
SELECT 
    t.id, 
    name.value('.','nvarchar(50)') as names, 
    dates.value('.','nvarchar(50)') as dates 
FROM t 
CROSS APPLY Col.nodes('/XMLDoc/AAA') as XMLtable1(AAA) 
CROSS APPLY XMLtable1.AAA.nodes('Name') as XMLtable2(name) 
CROSS APPLY XMLtable1.AAA.nodes('dateReported') as XMLtable3(dates) 
) 
select * 
from (
select 
    *, 
    rn = ROW_NUMBER() over (partition by id order by dates desc) 
from cte 
) t where rn = 1 
+0

我编辑了我的问题..请检查 – Saravanan 2015-03-02 12:04:54

0

对于更新的要求,以下SQL Server XML query使用可以帮助 请测试表,月内有一个以上的行查询重新准确的测试结果

;with cte as (
SELECT 
    t.id, 
    b.value('.','nvarchar(500)') as bbid, 
    c.value('.','nvarchar(500)') as cc, 
    name.value('.','nvarchar(50)') as names, 
    dates.value('.','nvarchar(50)') as dates 
FROM t 
CROSS APPLY Col.nodes('/XMLDoc/BB/ID') as XMLtable4(b) 
CROSS APPLY Col.nodes('/XMLDoc/CC') as XMLtable5(c) 
CROSS APPLY Col.nodes('/XMLDoc/x') as XMLtable0(d) 
CROSS APPLY XMLtable0.d.nodes('AAA') as XMLtable1(AAA) 
CROSS APPLY XMLtable1.AAA.nodes('Name') as XMLtable2(name) 
CROSS APPLY XMLtable1.AAA.nodes('dateReported') as XMLtable3(dates) 
) 
select * 
from (
select 
    *, 
    rn = ROW_NUMBER() over (partition by id order by dates desc) 
from cte 
) t where rn = 1