我希望返回一系列数值结果(即列的结果)并将这些逗号分开。因此,输出可以由另一个查询中的IN
子句使用。因此,当表数据如下时,我正在寻找 10,20,30,40,50,60 作为输出:
ID Value
1 10
2 20
3 30
4 40
5 50
6 60
最聪明的方法是什么?以下查询将以下列方式使用此输出字符串:
select * from Table where Value IN (10,20,30,40,50,60)
我尝试创建一个获取select输出的变量,但我只得到一个值。即
declare @Value_List varchar(799);
select @Value_List = Value from Table select @Value_List;
但是我只返回一个值,更不用说列表了。
理由是这是一个调试脚本,我们需要手动完成一系列检查,因此理想情况下要将查询分解为单个语句,以便于使用和清晰。
答案 0 :(得分:8)
要做你想做的事,你需要使用动态SQL。但是你能更好地解释为什么你想这样做吗?看起来要简单得多:
SELECT *
FROM Table
WHERE Value IN (SELECT Value FROM YourTable WHERE ID <= 6)
答案 1 :(得分: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)
*/
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 */);
3) 作为逗号分隔列表的更直接替代方案,请考虑Table-Valued Parameters。它们可以简单,易读,优雅(根据您对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
然后,您可以在一个查询中获取ID的“列表”(即设置),并在您描述的另一个查询中使用它:
DECLARE @fooIds dbo.IntTableType;
INSERT INTO @fooIds (Value)
SELECT IntColumn
FROM dbo.Whatever
WHERE 1 = 1; -- whatever
EXEC dbo.uspGetFoos @FooIdTable = @fooIds;
当然,您也可以类似地使用表变量或临时表来表示ID(前者仅限于单个存储过程,函数或批处理);但TVP为您提供了一种将表格(即设置)数据作为输入参数的一流方法。
答案 2 :(得分:0)
假设您的分隔值不像您的示例那样是线性的,您可以创建一个从分隔字符串返回表的函数。我复制了这个功能 here
CREATE FUNCTION [dbo].[func_Split]
(
@DelimitedString varchar(8000),
@Delimiter varchar(100)
)
RETURNS @tblArray TABLE
(
ElementID int IDENTITY(1,1), -- Array index
Element varchar(1000) -- Array element contents
)
AS
BEGIN
-- Local Variable Declarations
-- ---------------------------
DECLARE @Index smallint,
@Start smallint,
@DelSize smallint
SET @DelSize = LEN(@Delimiter)
-- Loop through source string and add elements to destination table array
-- ----------------------------------------------------------------------
WHILE LEN(@DelimitedString) > 0
BEGIN
SET @Index = CHARINDEX(@Delimiter, @DelimitedString)
IF @Index = 0
BEGIN
INSERT INTO
@tblArray
(Element)
VALUES
(LTRIM(RTRIM(@DelimitedString)))
BREAK
END
ELSE
BEGIN
INSERT INTO
@tblArray
(Element)
VALUES
(LTRIM(RTRIM(SUBSTRING(@DelimitedString, 1,@Index - 1))))
SET @Start = @Index + @DelSize
SET @DelimitedString = SUBSTRING(@DelimitedString, @Start , LEN(@DelimitedString) - @Start + 1)
END
END
RETURN
END
你的选择将是
select *
from Table
where Value IN (select Element from func_split('10,20,30,40,50,60', ','))
答案 3 :(得分:-1)
这应该连接
DECLARE @result VARCHAR(MAX)
SELECT @result = COALESCE(@result+' ,','')+Value FROM Table
SELECT @result