XML 个日期类型后代的 MIN

MIN of XML descendats of date type

如何查询 XML 字段中所有后代的最小日期。像这样:

DECLARE @xml XML ='
<Plan>
    <EffectiveDate>2006-01-01</EffectiveDate>
    <EffectiveDate>2016-09-14</EffectiveDate>
    <EffectiveDate>2016-09-14</EffectiveDate>
    <EffectiveDate>2016-09-14</EffectiveDate>
</Plan>'

SELECT @xml.value('min(descendant::EffectiveDate)','varchar(max)') minDate
    ,@xml.value('count(descendant::EffectiveDate)','varchar(max)') countDate

不幸的是在 returns 上面

为 NULL

试试这个。我认为这不是最好的解决方案(我期待在这里看到更好的解决方案)。但它会给你你想要的。 已编辑(我比较喜欢第二个)

DECLARE @x XML ='
<Plan>
    <EffectiveDate>2006-01-01</EffectiveDate>
    <EffectiveDate>2016-09-14</EffectiveDate>
    <EffectiveDate>2016-09-14</EffectiveDate>
    <EffectiveDate>2016-09-14</EffectiveDate>
</Plan>';

SELECT
    Min(a.EffDate) AS MinDate
    , Count(a.EffDate) AS CountDate
FROM
(
    SELECT
        EffDate.value('.','DATE') AS EffDate
    FROM
        @x.nodes('/Plan/EffectiveDate') AS Plans(EffDate)
)a;

这是第一个。

DECLARE @x XML ='
<Plan>
    <EffectiveDate>2006-01-01</EffectiveDate>
    <EffectiveDate>2016-09-14</EffectiveDate>
    <EffectiveDate>2016-09-14</EffectiveDate>
    <EffectiveDate>2016-09-14</EffectiveDate>
</Plan>';

DECLARE @DocHandle INT;
EXEC sp_XML_PrepareDocument @DocHandle OUTPUT, @x;

SELECT Min(a.EffDate) AS MinDate
, Count(a.EffDate) AS CountDate
FROM
(
SELECT *
FROM OPENXML(@DocHandle,'/Plan/EffectiveDate')
WITH (EffDate NVARCHAR(50) '.')
) a

EXEC sp_XML_RemoveDocument @DocHandle;

最简单的方法:

DECLARE @xml XML ='
<Plan>
    <EffectiveDate>2006-01-01</EffectiveDate>
    <EffectiveDate>2016-09-14</EffectiveDate>
    <EffectiveDate>2016-09-14</EffectiveDate>
    <EffectiveDate>2016-09-14</EffectiveDate>
</Plan>'

SELECT  MIN(t.v.value('.','date')) minDate,
        COUNT(t.v.value('.','date')) countDate
FROM @xml.nodes('//Plan/EffectiveDate') as t(v)

输出:

minDate     countDate
2006-01-01  4

非类型 xml 节点值的默认数据类型是 xdt:untypedAtomic。 min Function (XQuery) 将尝试将 xdt:untypedAtomic 值转换为 xs:double,然后 return 最小值。您的值无法转换为 xs:double,因此 min() 将 return 四个 null 值的最小值。

由于 min()xs:date 上工作得很好,您可以先将您的值转换为 xs:date,然后对日期值执行 min()

declare @xml xml = '
<Plan>
    <EffectiveDate>2006-01-01</EffectiveDate>
    <EffectiveDate>2016-09-14</EffectiveDate>
    <EffectiveDate>2016-09-14</EffectiveDate>
    <EffectiveDate>2016-09-14</EffectiveDate>
</Plan>';

select @xml.value('min(for $n in descendant::EffectiveDate/text() 
                       return $n cast as xs:date?)', 'date'),
       @xml.value('count(descendant::EffectiveDate)', 'int');