使用 CTE 递归替换字符串
Recursively replace string using a CTE
我有 lookup_table
如下:-
| id | Val |
+------+-----+
| 1 | A |
| 11 | B |
| 111 | C |
| 1111 | D |
我正在使用 lookup_table
中的值创建单词,例如 $id!
,并将其保存到另一个 table 中。
示例:差 - $11!$1!$1111!
所以我的 data_table
会是这样的,
| expression |
+-----------------+
| 1!!! | -- cab
| 11!!11! | -- dad
| !!11! | -- bad
我想反向构建 data_table 中的单词。
我试过的:在$
和!
上使用CHARINDEX
从表达式中获取第一个id并尝试替换它使用 CTE 递归地匹配来自 look_up table 的 val
。我没有得到我得到的确切结果,但通过一些 filetring,我得到了一些接近的结果。
我试过的查询:
;WITH cte AS
(SELECT replace(expression,'$' + CONVERT(varchar(10),id) + '!' ,val) AS 'expression',
cnt =1
FROM data_table
JOIN lookup_table ON id =
SUBSTRING(
SUBSTRING(expression, CHARINDEX('$', expression) + 1, LEN(expression) - CHARINDEX('$', expression)), 1, CHARINDEX('!', expression) - 2)
UNION ALL
SELECT replace(expression,'$' + CONVERT(varchar(10),id) + '!' ,val) AS 'expression' ,
cnt = cnt +1
FROM cte
JOIN lookup_table ON id =
SUBSTRING(
SUBSTRING(expression, CHARINDEX('$', expression) + 1, LEN(expression) - CHARINDEX('$', expression)), 1, CHARINDEX('!', expression) - (cnt +2))
WHERE CHARINDEX('$', expression) > 0 )
SELECT expression
FROM cte
WHERE CHARINDEX('$', expression) = 0
当前输出:
| expression |
+------------+
| DAD |
| CAB |
预期输出:
| expression |
+------------+
| DAD |
| CAB |
| BAD |
我做错了什么?
编辑: fiddler 中的数据设置有错别字。 d
糟糕的是有五个 1 而不是四个。谢谢 DarkRob 指出。
你可以试试这个。您可以使用多个 cte 来创建表达式,而不是使用递归 cte。由于 sql 已经引入了这个 string_split
函数来将您的行单元格转换为特定分隔符上的行,这将使我们的工作变得更加容易。
首先,我们将每个单元格值转换为单独的行。此外,我们可以通过使用 inner join with lookup table 轻松获得我们的表达词。在最后一次使用东西时,我们将再次获得我们需要的字符串。
;WITH CTE AS (
SELECT ROW_NUMBER() OVER (ORDER BY EXPRESSION) AS SLNO, * FROM data_table
),
CT AS (
SELECT *, REPLACE(VALUE,'$','') AS NEWVAL
FROM CTE CROSS APPLY string_split(EXPRESSION,'!') WHERE VALUE <> ''
),
CTFINAL AS (
SELECT * FROM CT INNER JOIN lookup_table AS LT ON CT.NEWVAL=LT.id
)
--SELECT * FROM CTFINAL
SELECT DISTINCT SLNO,
STUFF( (SELECT '' + VAL + '' FROM CTFINAL AS CFF WHERE CFF.SLNO=CF.SLNO FOR XML PATH('')), 1,0,'') AS MYVAL
FROM CTFINAL AS CF
我有 lookup_table
如下:-
| id | Val |
+------+-----+
| 1 | A |
| 11 | B |
| 111 | C |
| 1111 | D |
我正在使用 lookup_table
中的值创建单词,例如 $id!
,并将其保存到另一个 table 中。
示例:差 - $11!$1!$1111!
所以我的 data_table
会是这样的,
| expression |
+-----------------+
| 1!!! | -- cab
| 11!!11! | -- dad
| !!11! | -- bad
我想反向构建 data_table 中的单词。
我试过的:在$
和!
上使用CHARINDEX
从表达式中获取第一个id并尝试替换它使用 CTE 递归地匹配来自 look_up table 的 val
。我没有得到我得到的确切结果,但通过一些 filetring,我得到了一些接近的结果。
我试过的查询:
;WITH cte AS
(SELECT replace(expression,'$' + CONVERT(varchar(10),id) + '!' ,val) AS 'expression',
cnt =1
FROM data_table
JOIN lookup_table ON id =
SUBSTRING(
SUBSTRING(expression, CHARINDEX('$', expression) + 1, LEN(expression) - CHARINDEX('$', expression)), 1, CHARINDEX('!', expression) - 2)
UNION ALL
SELECT replace(expression,'$' + CONVERT(varchar(10),id) + '!' ,val) AS 'expression' ,
cnt = cnt +1
FROM cte
JOIN lookup_table ON id =
SUBSTRING(
SUBSTRING(expression, CHARINDEX('$', expression) + 1, LEN(expression) - CHARINDEX('$', expression)), 1, CHARINDEX('!', expression) - (cnt +2))
WHERE CHARINDEX('$', expression) > 0 )
SELECT expression
FROM cte
WHERE CHARINDEX('$', expression) = 0
当前输出:
| expression |
+------------+
| DAD |
| CAB |
预期输出:
| expression |
+------------+
| DAD |
| CAB |
| BAD |
我做错了什么?
编辑: fiddler 中的数据设置有错别字。 d
糟糕的是有五个 1 而不是四个。谢谢 DarkRob 指出。
你可以试试这个。您可以使用多个 cte 来创建表达式,而不是使用递归 cte。由于 sql 已经引入了这个 string_split
函数来将您的行单元格转换为特定分隔符上的行,这将使我们的工作变得更加容易。
首先,我们将每个单元格值转换为单独的行。此外,我们可以通过使用 inner join with lookup table 轻松获得我们的表达词。在最后一次使用东西时,我们将再次获得我们需要的字符串。
;WITH CTE AS (
SELECT ROW_NUMBER() OVER (ORDER BY EXPRESSION) AS SLNO, * FROM data_table
),
CT AS (
SELECT *, REPLACE(VALUE,'$','') AS NEWVAL
FROM CTE CROSS APPLY string_split(EXPRESSION,'!') WHERE VALUE <> ''
),
CTFINAL AS (
SELECT * FROM CT INNER JOIN lookup_table AS LT ON CT.NEWVAL=LT.id
)
--SELECT * FROM CTFINAL
SELECT DISTINCT SLNO,
STUFF( (SELECT '' + VAL + '' FROM CTFINAL AS CFF WHERE CFF.SLNO=CF.SLNO FOR XML PATH('')), 1,0,'') AS MYVAL
FROM CTFINAL AS CF