我有一个表格,其中有两列:optionValues
和optionNames
。
optionNames
包含组合框的文本和optionValues
每个文本的值,两者都用~
分隔。
例如:
optionValues | optionNames
0~1 | male~female
我正在尝试创建一个函数,它将optionValue作为参数并返回optionName。 使用上面的例子:
fn.GetOptionName(1) --will return `female`
我如何分离值并找回正确的值?
这是我开始使用但它无法工作,因为它没有分隔值:
select @on = OptionNames from dbo.Table
where tablename = @tablename and fieldname = @fieldname and optionvalues = @fieldvalue
(无论是好还是坏,我无法更改数据库架构)
修改
找到此函数,返回特定位置的子字符串: DelimitedSplit8K
答案 0 :(得分:2)
请尝试此操作(SQL 2016 +)
数据生成
CREATE TABLE Splits
(
optionValues varchar(20)
,optionNames varchar(200)
)
GO
INSERT INTO Splits VALUES
('0~1','male~female'),
('0~1~2','male~female~Trans'),
('0~1','male~F')
GO
<强>解强>
DECLARE @Find AS VARCHAR(10) = '1'
;WITH CTE0 AS
(
SELECT * , ROW_NUMBER() OVER (ORDER BY ( SELECT NULL ) ) rnk FROM Splits
)
,CTE AS
(
SELECT * , ROW_NUMBER() OVER (PARTITION BY rnk ORDER BY rnk) rnk1 FROM CTE0
CROSS APPLY
(
SELECT Value
FROM STRING_SPLIT(optionValues, '~'))
p
)
,CTE1 AS
(
SELECT * , ROW_NUMBER() OVER (PARTITION BY rnk ORDER BY rnk) rnk1 FROM CTE0
CROSS APPLY
(
SELECT Value
FROM STRING_SPLIT(optionNames, '~'))
p1
)
SELECT s.*,ISNULL(p.value,'') Value FROM Splits s
LEFT JOIN
(
SELECT a.optionValues, a.optionNames , b.value FROM CTE a
INNER JOIN CTE1 b ON a.optionNames = b.optionNames
AND a.optionValues = b.optionValues AND a.rnk = b.rnk AND a.rnk1 = b.rnk1
WHERE a.value = @Find
)p ON p.optionValues = s.optionValues AND p.optionNames = s.optionNames
<强>输出强>
optionValues optionNames Value
-------------------- ------------------------ ---------
0~1 male~female female
0~1~2 male~female~Trans female
0~1 male~F F
(3 rows affected)
为SQL 2012 +
解决方案添加DECLARE @Find AS VARCHAR(10) = '1'
;WITH CTE0 AS
(
SELECT * , ROW_NUMBER() OVER (ORDER BY ( SELECT NULL ) ) rnk FROM Splits
)
,CTE AS
(
SELECT * , ROW_NUMBER() OVER (PARTITION BY rnk ORDER BY rnk) rnk1 FROM
(
SELECT *,CAST('<A>'+ REPLACE(optionValues,'~','</A><A>')+ '</A>' AS XML) po
FROM CTE0
)rt
CROSS APPLY ( SELECT t.value('.', 'VARCHAR(10)') Value FROM po.nodes('/A') AS x(t) ) o
)
,CTE1 AS
(
SELECT * , ROW_NUMBER() OVER (PARTITION BY rnk ORDER BY rnk) rnk1 FROM
(
SELECT *,CAST('<A>'+ REPLACE(optionNames,'~','</A><A>')+ '</A>' AS XML) po
FROM CTE0
)rt
CROSS APPLY ( SELECT t.value('.', 'VARCHAR(10)') Value FROM po.nodes('/A') AS x(t) ) o
)
SELECT s.*,ISNULL(p.value,'') Value FROM Splits s
LEFT JOIN
(
SELECT a.optionValues, a.optionNames , b.value , a.rnk FROM CTE a
INNER JOIN CTE1 b ON a.optionNames = b.optionNames
AND a.optionValues = b.optionValues AND a.rnk = b.rnk AND a.rnk1 = b.rnk1
WHERE a.value = @Find
)p ON p.optionValues = s.optionValues AND p.optionNames = s.optionNames
ORDER BY rnk
<强>输出强>
optionValues optionNames Value
-------------------- ----------------------- ----------
0~1 male~female female
0~1~2 male~female~Trans female
0~1 male~F F
(3 rows affected)
答案 1 :(得分:0)
尝试以下脚本
declare @fieldvalue NVARCHAR(10) = '1' --Set parameter value here
,@V_Value NVARCHAR(100) --local variable1
,@V_Name NVARCHAR(100) --local variable2
SELECT @V_Value = optionValues
,@V_Name = optionNames
FROM fulltable --tablename here
WHERE '~'+optionvalues LIKE '%~'+@fieldvalue+'%'
AND tablename = @tablename
AND fieldname = @fieldname
SELECT ROW_VALUE1,ROW_VALUE2
FROM (
SELECT Split1.a.value('.', 'NVARCHAR(10)') AS ROW_VALUE1
,ROW_NUMBER() OVER(ORDER BY (SELECT 1)) AS ROW_NO1
FROM (
SELECT CAST('<X>'+REPLACE(@V_Value, '~', '</X><X>')+'</X>' AS XML) AS r1
) AS T1
CROSS APPLY r1.nodes('/X') AS Split1(a)
) AS A
OUTER APPLY (
SELECT Split2.a.value('.', 'NVARCHAR(10)') AS ROW_VALUE2
,ROW_NUMBER() OVER(ORDER BY (SELECT 1)) AS ROW_NO2
FROM (
SELECT CAST('<X>'+REPLACE(@V_Name, '~', '</X><X>')+'</X>' AS XML) AS r2
) AS T1
CROSS APPLY r2.nodes('/X') AS Split2(a)
) B
WHERE ROW_VALUE1 = @fieldvalue
AND A.ROW_NO1 = B.ROW_NO2
输出:
ROW_VALUE1 ROW_VALUE2
1 female