为什么递归的字符串连接内部子查询总是返回NULL?(Why subquery inside recu

2019-10-17 06:54发布

假设我有两个表:

  • 表1:具有标识我需要处理的清单。
  • TABLE2:有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,即使ID是表2中发现了什么?

Answer 1:

这是试图实现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想要的值,然后的替代变量@id,你只要相关子查询,如下table.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


Answer 2:

这是因为你是从0开始的@id除非你在你的表有0的ID,你可能需要做:SELECT @ ID = 1

或者,你可以把它浓缩到这一点,并没有使用id:

SELECT @value = @value + value +  '-'
FROM TABLE2 t2
INNER JOIN TABLE1 t1 ON t1.id = t2.id


Answer 3:

又一解决方案(这只是一个追加“ - ”表2从值之间的分隔符如果从表2的值是NOT NULL):

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)


文章来源: Why subquery inside recursive string concatenation always returns NULL?