SQL XML 基于XML 节点聚合函数的列过滤器

SQL XML Column filter based on XML node aggregate function

我有如下 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 的名称和值节点。到目前为止,我的 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,因为 AAA 的 datereported 具有最大值。

您可以尝试这样的操作 - 设置一个 CTE(通用 Table 表达式)以 "extract" 将 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)

在这种情况下可以使用以下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

对于更新后的要求,关注SQL Server XML query可以提供帮助 请测试 table 中超过一行的查询以获得更准确的测试结果

;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