select ET1.EntryID,
(
select ', '+T.Name
from Tags as T
inner join EntryTag as ET2
on T.TagID = ET2.TagID
where ET1.EntryID = ET2.EntryID
for xml path(''), type
).value('substring(text()[1], 3)', 'varchar(max)') as TagsCommaDelimited
from EntryTag as ET1
group by ET1.EntryID
Dissekerar frågan
Huvudfrågan gör en group by
så du får bara en rad för varje EntryID
.
Kolumnen TagsCommaDelimited
skapas med en korrelerad underfråga.
I SQL Server for xml path
används för att skapa en XML-representation av ett frågeresultat. Du har god kontroll över hur XML skapas genom att använda kolumnalias och parametrarna till path
och root
.
Det sammanlänkade värdet ', '+T.Name
i den korrelerade underfrågan kommer inte att ha ett kolumnnamn och den tomma parametern till for xml path('')
skapar xml utan några taggar alls. Det kommer bara att returneras ett textvärde.
När du lägger till type
till en for xml
fråga datatypen kommer att vara XML
.
För att få ut ett värde ur en XML bör du använda value()
metod. Du kan casta till en sträng men om du gjorde det skulle du till exempel få &
i strängen var du än har använt &
.
Den första parametern i value()
funktion är xQuery-uttrycket som används för att få det värde du vill ha. Använd text()
för att ange att du bara vill ha värdet för det aktuella elementet. [1]
talar om för SQL Server att du vill att den första textnoden ska hittas (du har bara en här) men det är fortfarande nödvändigt.
Strängen skapad av for xml
frågan har ett extra kommatecken och ett mellanslag i början av strängen och det måste tas bort. Här använder jag XQuery-funktionen substring
för att få allt utom de två första tecknen.
Den andra parametern till value()
anger vilken datatyp som ska returneras.