我有以下功能:
CREATE FUNCTION dbo.SplitStrings_XML
(
@List NVARCHAR(MAX),
@Delimiter NVARCHAR(255)
)
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN
(
SELECT Item = y.i.value('(./text())[1]', 'nvarchar(4000)')
FROM
(
SELECT x = CONVERT(XML, '<i>'
+ REPLACE(@List, @Delimiter, '</i><i>')
+ '</i>').query('.')
) AS a CROSS APPLY x.nodes('i') AS y(i)
);
GO
和以下代码:
declare @string nvarchar(max) = 'aaa,1.3,1,bbb,1.5,ccc,2.0,1'
;WITH AllItems as
(
SELECT Item, ROW_NUMBER() OVER(ORDER BY (select null)) as rn
FROM dbo.SplitStrings_XML(@string, ',')
)
, Strings as
(
SELECT Item as Name, ROW_NUMBER() OVER(ORDER BY (select null)) as rn
FROM dbo.SplitStrings_XML(@string, ',')
WHERE ISNUMERIC(Item) = 0
), Doubles as
(
SELECT Item as Measure, ROW_NUMBER() OVER(ORDER BY (select null)) as rn
FROM dbo.SplitStrings_XML(@string, ',')
WHERE ISNUMERIC(Item) = 1 AND CHARINDEX('.', Item) > 0
), Integers as
(
SELECT Item as Value, ROW_NUMBER() OVER(ORDER BY (select null)) as rn
FROM dbo.SplitStrings_XML(@string, ',')
WHERE ISNUMERIC(Item) = 1 AND CHARINDEX('.', Item) = 0
)
SELECT Name, Measure, Value
FROM AllItems A
LEFT JOIN Strings S ON A.rn = S.rn
LEFT JOIN Doubles D ON A.rn = D.rn
LEFT JOIN Integers I ON A.rn = I.rn
WHERE COALESCE(Name, Measure, Value) IS NOT NULL
在这段代码中,我们得到一个@string = 'aaa,1.3,1,bbb,1.5,ccc,2.0,1'
,它返回名为Name
的行中的字符,返回名为Measure
的行中的double值以及名为{的行中的int值{1}},问题是在我的字符串中我总是Value
但有时Name and Measure
丢失了,我想在该空格中放置一个NULL值。
所以在我的例子中我应该有像
这样的东西Value
相反,我有:
Name Measure Value
---------+--------+-------
aaa 1.3 1
bbb 1.5 NULL
ccc 2.0 1
答案 0 :(得分:2)
首先,我建议您修改函数以返回项目编号。但是,这不是必需的,因为您的row_number()
会这样做。
然后,我认为“缺失值”意味着“,,”。
如果是这样,我建议将CTE定义为:
WITH AllItems as (
SELECT Item, ROW_NUMBER() OVER (ORDER BY (select null)) as rn
FROM dbo.SplitStrings_XML(@string, ',')
),
Strings as (
SELECT Item as Name, ROW_NUMBER() OVER (ORDER BY (select null)) as rn
FROM AllItems ai
WHERE ai.rn % 3 = 1
),
Doubles as (
SELECT Item as Measure, ROW_NUMBER() OVER (ORDER BY (select null)) as rn
FROM AllItems ai
WHERE ai.rn % 3 = 2
),
Integers as (
SELECT Item as Value, ROW_NUMBER() OVER(ORDER BY (select null)) as rn
FROM AllItems ai
WHERE ai.rn % 3 = 0
)
. . .