比较 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;
理想情况下,您应该将每条信息存储在单独的行中,因此您应该有两个单独的表 roles
和 userroles
,它们在这个表上是外键的。
尽管如此,这并不需要游标。您可以使用 STRING_SPLIT
和 STRING_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 服务器的早期版本,则必须使用自定义 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;
这里我想比较角色和用户角色列中的逗号分隔值,然后在另一列中显示匹配值。
我找到了一个例子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;
理想情况下,您应该将每条信息存储在单独的行中,因此您应该有两个单独的表 roles
和 userroles
,它们在这个表上是外键的。
尽管如此,这并不需要游标。您可以使用 STRING_SPLIT
和 STRING_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 服务器的早期版本,则必须使用自定义 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;