更新:我完全清楚这是一个糟糕的RDBMS实践,但问题不在于它是否以及如何重新培训创建此体系结构的DBA。问题是如何解决我手头的情况。我很感谢社区的帮助,并且必须承认这确实是一个有趣的问题。
在SQL Server 2017中,我有一个包含代码的查找表和一个包含CSV格式代码的事务表:
CREATE TABLE #t(cd VARCHAR(100))
CREATE TABLE #cd (id INT, cd VARCHAR (1000))
INSERT INTO #t SELECT 'c1'
INSERT INTO #t SELECT 'c1,c2'
INSERT INTO #t SELECT 'c1,c2,c3'
INSERT INTO #cd SELECT 10, 'c1'
INSERT INTO #cd SELECT 20, 'c2'
INSERT INTO #cd SELECT 30, 'c3'
所以,查找是
id cd
10 c1
10 c1
20 c2
30 c3
并且,交易表具有:
cd
c1
c1,c2
c1,c2,c3
我需要将代码替换为各自的ID,同时将这些代码保留为CSV格式。
我想避开光标,因为它太慢了。有没有办法解析代码,执行JOIN,并以某种方式有效地重新组合ID?我认为COALESCE可能有用,但需要帮助应用它。也许,t-SQL中已经有一个函数可以执行这种类型的查找。
输出需要到事务表中的另一列:
id
10
10,20
10,20,30
答案 0 :(得分:1)
您可以先将逗号删除到列表中,然后加入并获取代码的正确ID,然后用逗号添加它们。我在前面使用了row_number来获取一个独特的东西,以便在我的查询中重新加入。
CREATE TABLE #t(cd VARCHAR(100))
CREATE TABLE #cd (id INT, cd VARCHAR (1000))
INSERT INTO #t SELECT 'c1'
INSERT INTO #t SELECT 'c1,c2'
INSERT INTO #t SELECT 'c1,c2,c3'
INSERT INTO #cd SELECT 10, 'c1'
INSERT INTO #cd SELECT 20, 'c2'
INSERT INTO #cd SELECT 30, 'c3'
; WITH X AS
(
SELECT
C.id,P1.rn
FROM
(
SELECT *, row_number() over( order by (select 1)) rn,
cast('<X>'+replace(P.cd,',','</X><X>')+'</X>' as XML) AS xmlitems FROM #t P
)P1
CROSS APPLY
(
SELECT fdata.D.value('.','varchar(100)') AS splitdata
FROM P1.xmlitems.nodes('X') AS fdata(D)) O
LEFT JOIN #cd C
ON C.cd= LTRIM(RTRIM(O.splitdata ))
)
SELECT
rn,
id= STUFF((
SELECT ',' + cast(id as varchar(100)) FROM X AS x2
WHERE x2.rn = x.rn
ORDER BY rn FOR XML PATH,
TYPE).value(N'.[1]',N'varchar(max)'), 1, 1, '')
FROM
X
GROUP BY rn
注意:使用SQL Server 2017,您还可以使用SPLIT_STRING()函数 和STRING_AGG()函数
SQL SERVER 2017代码:
select
id=STRING_AGG(id,',')
from
(
select V=value, rn
from
(
select
rn=row_number() over( order by (select 1)),
cd
from #T
)T
cross apply STRING_SPLIT(cd, ',')
) T
left join #cd C
on cd= v
group by rn