逗号分隔的查询结果,供SQL中的IN子句使用

dis*_*ive 1 sql t-sql sql-server

我希望返回一系列数值结果(即列的结果)并将这些逗号分开.因此,输出可以由IN另一个查询中的子句使用.因此,当表数据如下时,我正在寻找10,20,30,40,50,60作为输出:

ID   Value
1    10
2    20
3    30
4    40
5    50
6    60
Run Code Online (Sandbox Code Playgroud)

最聪明的方法是什么?以下查询将以下列方式使用此输出字符串:

select * from Table where Value IN (10,20,30,40,50,60)
Run Code Online (Sandbox Code Playgroud)

我已经尝试创建一个获取select输出的变量,但我只得到一个值.即

declare @Value_List varchar(799);
select @Value_List = Value from Table select @Value_List;
Run Code Online (Sandbox Code Playgroud)

但是我只返回一个值,更不用说列表了.

理由是这是一个调试脚本,我们需要手动完成一系列检查,因此理想情况下要将查询分解为单个语句,以便于使用和清晰.

Lam*_*mak 8

要做你想做的事,你需要使用动态SQL.但是你能更好地解释为什么你想这样做吗?看起来要简单得多:

SELECT * 
FROM Table 
WHERE Value IN (SELECT Value FROM YourTable WHERE ID <= 6)
Run Code Online (Sandbox Code Playgroud)


J0e*_*gan 6

1) 假设您的值列表没有像Lamak概述的更简单的方法解决(即您根本不需要列表),这里有一种使用动态SQL的方法:

-- Declare & get the list of values from a query.
DECLARE @values varchar(2000);
SET @values = '';
SELECT @values = @values + CAST(Value AS varchar(5)) + ','
FROM tbl_A; -- hopefully some WHERE criteria here to make this interesting

-- Trim the trailing comma.
SET @values = SUBSTRING(@values, 1, Len(@values) - 1)

---- DEBUG: Confirm the list of values.
--SELECT @values As 'Values'
--/*
--Values
-------------------------------------------------------------------------------
--10,20,30,40,50,60
--
--(1 row(s) affected)
--*/

-- Dynamically use the list of values in an IN clause.
DECLARE @sql as nvarchar(max);
SET @sql = 'SELECT Value FROM tbl_A WHERE Value IN (' + @values + ')';

EXEC sp_executesql @sql;
/*
Value
-----------
10
20
30
40
50
60

(6 row(s) affected)
*/
Run Code Online (Sandbox Code Playgroud)

SQLBook.com更深入地解释了这种方法.

2) 但是,当您可以使用一个子查询来获取IN子句中的值列表时,子查询会更智能- 例如:

SELECT a.Value
FROM tbl_A a
WHERE
    a.Value IN
        (SELECT b.Value
         FROM tbl_B b
         /* hopefully some WHERE criteria here to make this interesting */);
Run Code Online (Sandbox Code Playgroud)

3) 作为逗号分隔列表的更直接的替代方法,请考虑表值参数.它们可以简单,易读,优雅(根据您对Lamak的问题评论) - 即聪明.

考虑一个存储过程,它接受ID的"列表"作为ID的TVP(即集合):

/*
--------------------------------------------------------------------------------------
    IntTableType for int TVPs (i.e. "the TVP")
--------------------------------------------------------------------------------------
*/

CREATE TYPE [dbo].[IntTableType] AS TABLE
(
    Value int
)
GO


/*
--------------------------------------------------------------------------------------
    Gets a set of Foos by ID. (i.e. "the stored proc")
--------------------------------------------------------------------------------------
*/

CREATE PROCEDURE [dbo].[uspGetFoos]
    @FooIdTable dbo.IntTableType readonly
AS
BEGIN
    SET NOCOUNT ON;

    SELECT f.ID, f.Column1, f.Column2 -- etcetera
    FROM dbo.Foo f
    WHERE f.ID IN (SELECT fi.Value FROM @FooIdTable);

    ---- or --
    --
    --SELECT f.ID, f.Column1, f.Column2 -- etcetera
    --FROM dbo.Foo f
    --JOIN @FooIdTable fi ON fi.Value = f.ID;
END
GO
Run Code Online (Sandbox Code Playgroud)

然后,您可以在一个查询中获取ID的"列表"(即设置),并在您描述的另一个查询中使用它:

DECLARE @fooIds dbo.IntTableType;
INSERT INTO @fooIds (Value)
SELECT IntColumn
FROM dbo.Whatever
WHERE 1 = 1; -- whatever

EXEC dbo.uspGetFoos @FooIdTable = @fooIds;
Run Code Online (Sandbox Code Playgroud)

当然,您也可以类似地使用表变量或临时表来表示ID(前者仅限于单个存储过程,函数或批处理); 但TVP为您提供了一种将表格(即设置)数据作为输入参数的一流方法.