sql server 2012:函数获取给定字符串的位置,然后获取给定位置的字符串

时间:2018-01-18 08:35:14

标签: sql sql-server function sql-server-2012

我有一个表格,其中有两列:optionValuesoptionNamesoptionNames包含组合框的文本和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

2 个答案:

答案 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