you*_*gme 4 sql-server t-sql sql-server-2016 string-manipulation
给定一个包含两列的表 - 一个整数 ID 和一个基于文本的字符串 - 我想从一个字符串值开始,该字符串值对用大括号括起来的任意数量的整数进行编码,并与任何其他有效文本字符混合。
例子:'{1} / {9} ... {12}'
通过一条SELECT
语句,我想返回一个字符串,其中所有整数(及其大括号)都已替换为从我的表派生的值;具体来说,行的文本值的 ID 与源字符串中找到的数字相匹配......并且大括号之外的任何字符保持不变。
这是一个未能完成任务的示例:
select
replace('{13} {15}','{'+cast(id as varchar)+'}',isNull(display,''))
from testing;
Run Code Online (Sandbox Code Playgroud)
这将在表中每行返回 1 行testing
。对于值 = 13 的行id
,字符串的“{13}”部分已成功替换,但“{15}”部分未成功替换(第 15 行反之亦然)。
我想创建一个循环所有testing
行并重复尝试替换的函数可以解决问题。尽管如此,直接的 SQL 语句比循环语句更好。
示例数据
+----+-------------------+
| id | display |
+----+-------------------+
| 1 | Apple |
| 2 | Banana |
| 3 | Celery |
| 4 | Dragonfruit |
| 5 | Eggplant |
| 6 | Fenugreek |
| 7 | Gourd |
| 8 | Honeydew |
| 9 | Iceberg Lettuce |
| 10 | Jackfruit |
| 11 | Kale |
| 12 | Lemon |
| 13 | Mandarin |
| 14 | Nectarine |
| 15 | Olive |
+----+-------------------+
Run Code Online (Sandbox Code Playgroud)
示例用例
select replace('{1} {3}',null,null)
-- Returns 'Apple Celery'
select replace('{3},{4},{5}',null,null);
-- Returns 'Celery,Dragonfruit,Eggplant'
select replace('{1} / {9} ... {12}',null,null);
-- Returns 'Apple / Iceberg Lettuce ... Lemon'
Run Code Online (Sandbox Code Playgroud)
显然,replace
关键字不起作用。
附言。如果解决方案需要更改字符串的格式以促进此目的,那么这是一个选项。
例如:('#1 / #9 ... #12'
与前面的示例相关)
在这种格式中,也许我们可以将字符串分解为一个行集,基于 ,#
获取left
字符直到找到非数字,根据获取的数字到表中,将join
和数字替换为表的值,然后将所有这些单独将标记修改回单个字符串?testing
#
testing
display
stuff
for xml path
我使用的是 SQL Server 2016,它不支持string_agg
. 也就是说,如果有一个使用 的解决方案string_agg
,我仍然有兴趣审查它。
cte
这是使用递归来翻译变量的示例
drop table if exists testing;
go
create table testing (id int, display varchar(16));
insert into testing values (1, 'Apple');
insert into testing values (2, 'Banana');
insert into testing values (3, 'Celery');
insert into testing values (4, 'Dragonfruit');
insert into testing values (5, 'Eggplant');
DROP FUNCTION IF EXISTS dbo.TranslateVariables
go
CREATE FUNCTION dbo.TranslateVariables
(
@StringValue VARCHAR(MAX)
)
RETURNS TABLE
AS
RETURN (
--Common Table Expression for Translation
WITH TranslationTable
AS (
SELECT FindValue = '{' + convert(varchar(5),id) + '}' ,ReplaceValue = display,ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS rn
FROM testing
)
--Recursive CTE to loop through the TranslationTable and replace FindValue with ReplaceValue
,RecursiveCte as
(
SELECT @StringValue AS StrValue
,(
SELECT count(*)
FROM TranslationTable
) AS cnt
UNION ALL
SELECT replace(StrValue, tt.FindValue, tt.Replacevalue)
,cnt - 1
FROM RecursiveCte
JOIN TranslationTable tt
ON tt.rn = cnt )
SELECT StrValue
,cnt
FROM RecursiveCte where cnt = 0
)
go
Run Code Online (Sandbox Code Playgroud)
--Verify translation
SELECT *
FROM dbo.TranslateVariables('{1} {3}')
OPTION (MAXRECURSION 32767) -- Don't forget to use the maxrecursion option!
Run Code Online (Sandbox Code Playgroud)
StrValue | cnt |
|--------------|-----|
| Apple Celery | 0 |
Run Code Online (Sandbox Code Playgroud)
SELECT *
FROM dbo.TranslateVariables('{3},{4},{5}')
OPTION (MAXRECURSION 32767) -- Don't forget to use the maxrecursion option!
Run Code Online (Sandbox Code Playgroud)
| StrValue | cnt |
|-----------------------------|-----|
| Celery,Dragonfruit,Eggplant | 0 |
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
8046 次 |
最近记录: |