Return SQL 服务器上某些列中值爆炸的日期

Return date from value exploded in some columns on SQL Server

我想 return 在 SQL 服务器上用斜杠展开的每个字符串的日期。

我的数据库table:

id | date       | col1        | col2      | col3  | col4
---+------------+-------------+-----------+-------+------------
1  | 2017-04-02 | /txt1/txt2  |           |       |
2  | 2017-04-03 |             | /txt1/txt4|       |
3  | 2017-04-04 |             |/txt2/txt3 |       |
4  | 2017-04-05 |             |/txt4      |       |/txt5/txt6

想要的结果:

2017-04-02 txt1
2017-04-02 txt2
2017-04-03 txt1
2017-04-03 txt4
2017-04-04 txt2
2017-04-04 txt3
2017-04-05 txt4
2017-04-05 txt5
2017-04-05 txt6

谢谢 皮埃尔

假设您不能使用 STRING_SPLIT() function(可从 SQL Server 2016 获得),您首先需要一个函数来标记 varchar 列。网络上有数百个,不过我会选择最合适且经过充分测试的,由您自己决定。

对于我的示例,我将使用 this,它适用于您的示例:

CREATE FUNCTION [dbo].[fnSplitString] 
( 
    @string NVARCHAR(MAX), 
    @delimiter CHAR(1) 
) 
RETURNS @output TABLE(splitdata NVARCHAR(MAX) 
) 
BEGIN 
    DECLARE @start INT, @end INT 
    SELECT @start = 1, @end = CHARINDEX(@delimiter, @string) 
    WHILE @start < LEN(@string) + 1 BEGIN 
        IF @end = 0  
            SET @end = LEN(@string) + 1

        INSERT INTO @output (splitdata)  
        VALUES(SUBSTRING(@string, @start, @end - @start)) 
        SET @start = @end + 1 
        SET @end = CHARINDEX(@delimiter, @string, @start)

    END 
    RETURN 
END

应用分割函数

select t.date, x.splitdata 
from test t 
cross apply dbo.fnSplitString(
   coalesce(col1, '') + coalesce(col2, '') 
   + coalesce(col3, '') + coalesce(col4, '')
, '/') x
where coalesce(x.splitdata, '') <> ''

rextester demo

请注意,在演示中我使用了 Id 列而不是 date 列。

每个人都应该有一个很好的 split/parse 功能作为 Zohar Peled 链接到。

如果您不能使用(或想要)UDF,这是另一种选择。

例子

Select A.Date
      ,C.RetVal
 From  YourTable A
 Cross Apply (values (col1),(col2),(col3),(col4)) B (Value)
 Cross Apply (
                Select RetSeq = Row_Number() over (Order By (Select null))
                      ,RetVal = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)')))
                From  (Select x = Cast('<x>' + replace((Select replace(B.Value,'/','§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml).query('.')) as A 
                Cross Apply x.nodes('x') AS B(i)
             ) C
 Where C.RetVal is not null

Returns

Date        RetVal
2017-04-02  txt1
2017-04-02  txt2
2017-04-03  txt1
2017-04-03  txt4
...