在子查询中返回逗号分隔的列表的SQL

时间:2021-02-12 00:19:34

Say I have a field in a SQL table (Locations) whose value is a semi-colon separated list:

假设我在SQL表(位置)中有一个字段,它的值是分号列表:

username1;username2;username3

If I say:

如果我说:

SELECT '''' + REPLACE(owners, ';', ''',''') + '''' FROM Locations WHERE ...

I can get it to output:

我可以把它输出:

'username1','username2','username3'

... but what I want to do is then use that in a subquery:

…但是我想做的是在子查询中使用这个

SELECT * FROM Users WHERE UserName IN (   
    SELECT '''' + REPLACE(owners, ';', ''',''') + '''' 
    FROM Locations WHERE ...
)

So, essentially I want the output of that subquery to act as a string in the IN() clause. Is this possible?

本质上,我希望子查询的输出作为in()子句中的字符串。这是可能的吗?

Thanks!

谢谢!

2 个解决方案

#1


5  

No you can't do what you are trying to do, construct 'username1','username2','username3' at runtime.

不,你不能做你想做的事,在运行时创建username1, username2, username3。

yet a simpler solution would be to use a split function

然而,一个更简单的解决方案是使用拆分函数。

Split function

CREATE FUNCTION [dbo].[Split]
(
  @delimited nvarchar(max),
  @delimiter nvarchar(100)
) 
RETURNS @t TABLE (id int identity(1,1), val nvarchar(max))
AS
BEGIN
  declare @xml xml
  set @xml = N'<root><r>' + replace(@delimited,@delimiter,'</r><r>') + '</r></root>'

  insert into @t(val)
  select
    r.value('.','varchar(max)') as item
  from @xml.nodes('//root/r') as records(r)

  RETURN
END

Query

SELECT *
FROM [Users] u 
WHERE u.UserName IN (  SELECT val 
                       FROM [Location] l
                                    CROSS APPLY [dbo].[Split](l.owners, ';')
                    );

#2


0  

If the inner select returns only one row you can use CHARINDEX:

如果内部选择只返回一行,则可以使用CHARINDEX:

SELECT * FROM Users WHERE CHARINDEX(''''+UserName+'''', (
   SELECT '''' + REPLACE(owners, ';', ''',''') + '''' 
   FROM Locations WHERE ...
)) > 0

#1


5  

No you can't do what you are trying to do, construct 'username1','username2','username3' at runtime.

不,你不能做你想做的事,在运行时创建username1, username2, username3。

yet a simpler solution would be to use a split function

然而,一个更简单的解决方案是使用拆分函数。

Split function

CREATE FUNCTION [dbo].[Split]
(
  @delimited nvarchar(max),
  @delimiter nvarchar(100)
) 
RETURNS @t TABLE (id int identity(1,1), val nvarchar(max))
AS
BEGIN
  declare @xml xml
  set @xml = N'<root><r>' + replace(@delimited,@delimiter,'</r><r>') + '</r></root>'

  insert into @t(val)
  select
    r.value('.','varchar(max)') as item
  from @xml.nodes('//root/r') as records(r)

  RETURN
END

Query

SELECT *
FROM [Users] u 
WHERE u.UserName IN (  SELECT val 
                       FROM [Location] l
                                    CROSS APPLY [dbo].[Split](l.owners, ';')
                    );

#2


0  

If the inner select returns only one row you can use CHARINDEX:

如果内部选择只返回一行,则可以使用CHARINDEX:

SELECT * FROM Users WHERE CHARINDEX(''''+UserName+'''', (
   SELECT '''' + REPLACE(owners, ';', ''',''') + '''' 
   FROM Locations WHERE ...
)) > 0