将 STUFF 与 DATE 一起使用

Posted

技术标签:

【中文标题】将 STUFF 与 DATE 一起使用【英文标题】:Using STUFF with DATE 【发布时间】:2019-01-29 11:42:09 【问题描述】:

我正在尝试使用 SQL Server 2016 中的 STUFF 功能来选择 DATE 信息并将其返回到表中。有时会有多个日期返回。我已经使用 STUFF 来获取我需要的其他数据。

Email = STUFF((SELECT ', ' + [Value] 
  FROM EmailTable  
    WHERE ID = r.ID AND EmailType = 1 
      FOR XML PATH(''),TYPE).value('(./text())[1]','NVARCHAR(MAX)'),1,2,'')

这可以在适用的情况下返回多封电子邮件并且工作正常。现在的问题是我想做同样的事情,但要使用 DATE。

Date = STUFF((SELECT ', ' + DateValue 
  FROM DateTable  
    WHERE ID = r.ID
      FOR XML PATH(''),TYPE).value('(./text())[1]','DATE'),1,2,'')  

上面的代码sn-ps只是例子,表名和变量名在现实中是不同的,但它们应该能传达我的意思。

最后一个代码sn-p的错误是因为'+'符号它不起作用。如果我把逗号加出来,我可以让它返回 DATE,但它们被包裹在 XML 标记中。

它还必须返回一个 DATE 值,它不能转换为 NVARCHAR。

我不确定我所追求的是否可行,但我想我会问。

如果需要更多信息,请询问。

【问题讨论】:

您正在尝试连接字符串,而不是将STUFFDATE 一起使用。 SQL Server 2017 引入了 STRING_AGG,因此无需使用此类字符串连接技术。 你能分享示例输入和所需的输出 @Panagiotis 目前我无法使用 SQL Server 2017。 由于您想连接字符串,并且不想让日期格式留给机会,请使用FORMAT() 将日期格式化为您想要的字符串 “它还必须返回一个 DATE 值”——“它”指的是什么?您将一堆日期连接成一个字符串。不管怎样,这不会是一个单一的DATE 值。添加更多输入和所需输出可能会有所帮助。 【参考方案1】:

评论太长了。

您的代码不能在单个列中返回多个日期。 SQL Server 不提供数组类型 - 或它们的等价物。

FOR XML PATH 所做的是产生一个字符串。该字符串被格式化为 XML,但它仍然是一个字符串。在字符串中,您可以识别属性的类型。但是,表示形式是字符串。

您可以做的最好的是将日期存储为 YYYY-MM-DD 或 YYYYMMDD,这很容易在 SQL Server(以及几乎任何其他软件)中转换为日期。

【讨论】:

我明白了。感谢您简单地为我介绍,现在一切都说得通了。我太专注于问题的 DATE 部分,而忽略了我正在尝试使用 XML 的事实。【参考方案2】:

您在旧 SQL Server 版本中使用的字符串聚合技术中发布的内容。 SQL Server 2017 为此提供了 STRING_AGG。

此技术使用空字符串作为元素名称从查询中生成 XML 值。 .value('(./text())[1]','NVARCHAR(MAX)') 最后将 XML 值转换为 text 。最后,STUFF, 1,2,'') 删除了前导分隔符。

由于您想要连接字符串,并且不想让日期格式留给机会,请使用 FORMAT() 将日期格式化为您想要的字符串:

Email = STUFF((SELECT ', ' + FORMAT([DateValue],'yyyy-MM-dd')
                   FROM EmailTable  
                   WHERE ID = r.ID AND EmailType = 1 
                   FOR XML PATH(''),TYPE
               ).value('(./text())[1]','NVARCHAR(MAX)'),
              1,2,'')

工作原理

x作为元素名执行最里面的查询:

SELECT ', ' + format(DateValue,'yyyy-MM-dd')
FROM EmailTable
WHERE year=2019 and Day<5 and month=1
FOR XML PATH('x'),TYPE

会返回:

<x>, 2019-01-01</x>
<x>, 2019-01-02</x>
<x>, 2019-01-03</x>
<x>, 2019-01-04</x>

通过指定空字符串作为元素,我们得到:

, 2019-01-01, 2019-01-02, 2019-01-03, 2019-01-04

这仍然是一个 XML 值,其内部文本是我们想要的字符串。我们需要使用.value('(./text())[1]','nvarchar(max)') 提取它:

select (  SELECT ', ' + format(DateValue,'yyyy-MM-dd')
          FROM EmailTable
          WHERE year=2019 and Day<5 and month=1
         FOR XML PATH(''),TYPE
       ).value('(./text())[1]','nvarchar(max)')

之后,我们需要删除前导分隔符,在这种情况下,两个字符 . T-SQL doesn't have aREMOVEstring function andSUBSTRINGneeds a length.STUFF` 删除在附加一个指定数量的字符之前新字符串,因此它可用于从开头删除文本。

【讨论】:

以上是关于将 STUFF 与 DATE 一起使用的主要内容,如果未能解决你的问题,请参考以下文章

将 DATE 函数与 HSQL 一起使用时出错

不能将 $match 与 mongoose 和聚合框架一起使用

不能将 $match 与 mongoose 和聚合框架一起使用

使用 distinct with stuff/for xml path('')

如何将GROUP BY与AGGREGATED列值一起使用

如何将循环与 geom_vline 和 facet_wrap 一起使用?