Warum Unterabfrage innerhalb rekursiver String-Verkettung immer NULL zurückgibt?

Angenommen, ich habe zwei Tische:

  • TABELLE 1: Hat eine list von IDs, die ich verarbeiten muss.
  • TABELLE 2: Schlüssel-Wert-Paare von IDs und Werten.

Ich muss die Werte aus TABLE2 für alle IDs in TABELLE 1 als einen einzigen String abrufen. Um dies zu erreichen, habe ich die nächste Abfrage gemacht:

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 

Aber wenn ich diese Abfrage ausführe, gibt die Unterabfrage immer null zurück (und daher @value=NULL am Ende). Meine Frage ist: Warum ist die Unterabfrage SELECT TOP 1 value FROM TABLE2 WHERE id=@id immer NULL zurückgibt, auch wenn die ID in TABLE2 gefunden wird?

Dies ist eine sehr seltsame Art zu versuchen, einen Treewalker zu implementieren, erhöhen @id in der SELECT und erwartet, dass es auf die Unterabfrage gelten. Es funktioniert nicht, da SQL server den Wert von @id für den Unterabfrage-Ausdruck als Konstante rechts in der Abfrage-Setup-Phase sperrt.

Sehen Sie dieses Beispiel, wo der zurückgegebene @ -Wert eindeutig anzeigt, dass @id bei 1 gesperrt ist. Mit Ihrer Frage wurde es bei 0 gesperrt, daher wird jede Unterabfrage NULL zurückgeben, angeblich weil es keine Übereinstimmung für @id = 0 gibt.

 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 

Wenn du nur die Werte von 2 wünschst, dann kannst du statt der variables @id die Unterabfrage mit der table.id wie folgt korrelieren:

 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 

Es ist, weil du dein @id bei 0 anfängst. Wenn du keine ID von 0 in deiner Tabelle hast, musst du wahrscheinlich tun: SELECT @ id = 1

Alternativ könntest du es dazu kondensieren und nutzt die ID nicht:

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

Noch eine andere Lösung (diese hängt nur das '-' – Trennzeichen zwischen den Werten aus Tabelle2 an, wenn der Wert von table2 NICHT NULL ist):

 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)