【问题标题】:Compare 2 columns value in a table and show the matching values in a new column . column values are comma seperated比较表中的 2 列值并在新列中显示匹配值。列值以逗号分隔
【发布时间】:2021-08-23 06:43:58
【问题描述】:

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

我找到了一个示例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)

下面是我要找的结果表。

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;

【问题讨论】:

  • 请向我们展示您的尝试。
  • @DaleK 添加了我的尝试并仍在尝试。我确信我没有以有效的方式解决这个问题。应该有更好的方法。
  • @DaleK 我更新了我的尝试,到目前为止它对我有用。有没有更好的方法来实现这一目标?任何帮助深表感谢。提前致谢
  • 您的 SQL Server 是 2016 还是更高版本?
  • @MarcusViniciusPompeu sql server 2016

标签: sql sql-server tsql split compare


【解决方案1】:

理想情况下,您应该将每条单独的信息存储在单独的行中,因此您应该有两个单独的表 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 Server,则必须使用自定义表值函数来执行此操作。

【讨论】:

  • @Charlieface 非常感谢。对于较低版本,我使用 STUFF FOR XML 代替 STRING_AGG 并且它有效
【解决方案2】:

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

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;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-31
    • 2010-12-09
    • 1970-01-01
    • 2011-01-26
    • 1970-01-01
    • 2020-06-12
    相关资源
    最近更新 更多