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, '') <> ''
请注意,在演示中我使用了 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
...
我想 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, '') <> ''
请注意,在演示中我使用了 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
...