比较 table 中的 2 列值并在新列中显示匹配值。列值以逗号分隔

Compare 2 columns value in a table and show the matching values in a new column . column values are comma seperated

这里我想比较角色和用户角色列中的逗号分隔值,然后在另一列中显示匹配值。

我找到了一个例子compare comma separated values in sql并使用游标逐行迭代。它对我有用。但我觉得应该有更好的方法。

非常感谢任何帮助。

Create table #temp4
(
 user_id int,
 permission_id int, 
 roles varchar(max), 
 userroles varchar(max), 
 matchingrolesinthisrow varchar(max))

Insert Into #temp4 values 
( 1, -12010, '2341,8760,3546', '1000,1001,1002,1003', null),
( 1, -334,   '1002,1001,3467',      '2341,1002,3467', null),
( 2, -12349, '9876,9982,6548', '1001,1002,2341', null)

下面是我要找的结果table。

user_id permission_id roles userroles matchingrolesinthisrow
1 -12010 2341,8760,3546 1000,1001,1002,1003
1 -334 1002,1001,3467 2341,1002,3467 1002,3467
2 -12349 9876,9982,6548 1001,1002,2341

到目前为止我的尝试是有效的。请指导我以更好的方式做到这一点。

DECLARE @user_id INT
DECLARE @permission_id INT
DECLARE @roles VARCHAR(MAX)
DECLARE @userroles VARCHAR(MAX)
DECLARE @matchingrolesinthisrow VARCHAR(MAX)
declare cur CURSOR LOCAL for
    select user_id, permission_id, roles, userroles, matchingrolesinthisrow  from #temp4 order by 1
 
open cur
 
fetch next from cur into @user_id, @permission_id, @roles, @userroles, @matchingrolesinthisrow
 
while @@FETCH_STATUS = 0 BEGIN
 
 print (@roles)
 print(@userroles)
    --execute  on each row 
    UPDATE #temp4 
    SET matchingrolesinthisrow = T1.[Item] 
    FROM [developers].[Split](@roles, ',') AS T1
    INNER JOIN [developers].[Split](@userroles, ',') AS T2 on T1.[Item] = T2.[Item]
    Where roles = @roles and userroles = @userroles and permission_id = @permission_id and user_id = @user_id

    fetch next from cur into @user_id, @permission_id, @roles, @userroles, @matchingrolesinthisrow
END
 
close cur
deallocate cur



--Split function
CREATE FUNCTION [developers].[Split] 
(   
    @s VARCHAR(max),
    @split CHAR(1)
)
RETURNS @temptable TABLE ([Item] VARCHAR(MAX))    
AS
BEGIN
    DECLARE @x XML

    SELECT @x = CONVERT(xml,'<root><s>' + REPLACE(@s,@split,'</s><s>') + '</s></root>');

    INSERT INTO @temptable          
    SELECT [Value] = T.c.value('.','varchar(20)')
    FROM @X.nodes('/root/s') T(c);
RETURN
END;

理想情况下,您应该将每条信息存储在单独的行中,因此您应该有两个单独的表 rolesuserroles,它们在这个表上是外键的。

尽管如此,这并不需要游标。您可以使用 STRING_SPLITSTRING_AGG 来非常轻松地获得您想要的结果:

SELECT
  t4.user_id,
  t4.permission_id,
  t4.roles,
  t4.userroles,
  matchingrolesinthisrow = (
    SELECT STRING_AGG(r.value, ',')
    FROM STRING_SPLIT(t4.roles, ',') r
    JOIN STRING_SPLIT(t4.userroles, ',') ur ON ur.value = r.value
  )
FROM #temp4 t4;

SQL Fiddle

如果您使用的是 SQL 服务器的早期版本,则必须使用自定义 Table 值函数来执行此操作。

修改了共享答案以在较低版本的 SQL 服务器中工作。

SELECT
  t4.user_id,
  t4.permission_id,
  t4.roles,
  t4.userroles, 
 STUFF((SELECT N',' + CONVERT(nvarchar(2000),r.value) 
 FROM STRING_SPLIT(t4.roles, ',') r
 INNER JOIN STRING_SPLIT(t4.userroles, ',') ur ON ur.value = r.value
FOR XML PATH(N''), TYPE).value(N'.[1]', N'nvarchar(max)'), 1, 1, N'') as matchingrolesinthisrow
FROM #temp4 t4;