在DATE使用STUFF

时间:2019-01-29 11:42:09

标签: sql sql-server date sql-server-2017 sql-server-group-concat

我正在尝试使用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,'')  

上面的代码片段只是示例,表和变量名称实际上是不同的,但是它们应该传达我的理解。

最后一个代码段的错误是由于'+'符号,它无法正常工作。如果我用逗号加上加号,我可以得到它返回DATE,但是它们被封装在XML标记中。

此外,它还必须返回DATE值,无法将其转换为NVARCHAR。

我不确定我追求的目标是否可行,但我想问一下。

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

2 个答案:

答案 0 :(得分:1)

这个评论太长了。

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

FOR XML PATH的作用是产生一个 string 。该字符串的格式为XML,但仍为字符串。在字符串中,您可以标识属性的类型。但是,表示形式是字符串。

最好的办法是将日期存储为YYYY-MM-DD或YYYYMMDD,可以很容易地将其转换为SQL Server(以及几乎所有其他软件)中的日期。

答案 1 :(得分:1)

您发布的内容采用了旧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 a REMOVE string function and SUBSTRING needs a length. STUFF` 删除附加新字符串之前的字符数,因此可用于从头开始删除文本。