1

假设我有两张桌子:

  • 表 1:有一个我需要处理的 ID 列表。
  • 表 2:具有 ID 和值的键值对。

我需要从 TABLE2 中检索 TABLE1 中所有 ID 的值,作为单个字符串。为了实现这一点,我进行了下一个查询:

DECLARE @id INT, @value VARCHAR(10);

SELECT @id=0, @value='';

SELECT
    @value = @value + (SELECT TOP 1 value FROM TABLE2 WHERE id=@id) + '-',
    @id = @id+1
FROM TABLE1

但是当我运行这个查询时,子查询总是返回 null (因此,@value=NULL最后)。我的问题是:为什么子查询SELECT TOP 1 value FROM TABLE2 WHERE id=@id总是返回 NULL,即使在 TABLE2 中找到了 ID?

4

3 回答 3

4

这是尝试实现 treewalker 的一种非常奇怪的方式,在 SELECT 中增加 @id 并期望它应用于子查询。它不起作用,因为 SQL Server 在查询设置阶段将子查询表达式的 @id 值锁定为常量。

请参阅此示例,其中返回的@value 清楚地表明@id 被锁定为 1。对于您的问题,它被锁定为 0,因此每个子查询将返回 NULL,表面上是因为 @id = 0 不匹配。

create table table1 (
  id int);
create table table2 (
  id int, value varchar(10));
insert table1 values (1),(2),(3),(4);
insert table2 values
(1,1),
(2,2),
(3,3),
(4,4);

DECLARE @id INT, @value VARCHAR(10);

SELECT @id=1, @value='';

SELECT
    @value = @value + (SELECT TOP 1 value FROM TABLE2 WHERE id=@id) + '-',
    @id = @id+1
FROM TABLE1;

select @value, @id

-- result
1-1-1-1       5

如果您只想要 2 中的值,那么您只需将子查询与 table.id 相关联,而不是变量 @id,如下所示:

create table table1 (id int);
create table table2 (id int, value varchar(10));
insert table1 values (1),(2),(3),(4);
insert table2 values
(1,1),
(3,9),
(4,4);

DECLARE @value VARCHAR(10);

SELECT @value='';

SELECT
    @value = @value + isnull((SELECT TOP 1 value 
                              FROM TABLE2 
                              WHERE id=table1.id) + '-','')
FROM TABLE1;

select @value

-- Result
1-9-4
于 2012-09-28T21:48:09.213 回答
1

还有另一种解决方案(如果 table2 中的值不为空,则此解决方案仅在 table2 中的值之间附加“-”分隔符):

declare @id int, @value varchar(max);
select @id = 0, @value='';

select 
    @value = @value + isnull(value,'') + case when value is null then '' else '-' end
from 
    table2 t2
where 
    t2.id in (select id from table1)
于 2012-09-28T21:52:58.243 回答
1

这是因为您从 0 开始 @id。除非您的表中的 id 为 0,否则您可能需要这样做:SELECT @id=1

或者,您可以将其压缩为此而不使用 id:

SELECT @value = @value + value +  '-'
FROM TABLE2 t2
INNER JOIN TABLE1 t1 ON t1.id = t2.id
于 2012-09-28T21:56:25.843 回答