В языке SQL нет слова "Свернуть". То, что вы опубликовали, показывает группировку и агрегирование. Для строк единственными значимыми агрегатами являются MIN, MAX и конкатенация строк.
SQL Server 2017 обеспечивает конкатенацию строк с помощью функции STRING_AGG
. Другие продукты баз данных используют другие имена, например GROUP_CONCAT
. В более ранних версиях SQL Server для достижения этой цели использовались различные методы. То, что вы опубликовали, - это техника XML.
Однако в запросе нет предложения GROUP BY, поэтому возвращается несколько строк.
В SQL Server 2017 запрос будет выглядеть следующим образом:
select T1.Id,
T1.Name,
MIN(T2.Id) as T2_ID,
MIN(T2.T1_Id) as T1_ID,
MIN(T2.Name) as T2_Name,
STRING_AGG(T3.Name,', ') as Test5
from @Test1 T1
inner join @Test2 T2 on T1.Id=T2.T1_Id
inner join @Test3 T3 on T3.Id=T2.T3_Id
GROUP BY T1.ID,T1.Name
Делать то же самое в более ранних версиях сложнее. Запрос FOR XML
может коррелировать только со столбцами, которые появляются в предложении GROUP BY:
select T1.Id,
T1.Name,
MIN(T2.Id),
MIN(T2.T1_Id),
MIN(T2.Name),
stuff(
(
SELECT ','+T3.Name
FROM @Test3 T3
inner join @Test2 TT2 on T3.Id=TT2.T3_Id
WHERE TT2.T1_ID=T1.Id
FOR XML PATH('')
),1,1,'') as Test5
from @Test1 T1
inner join @Test2 T2 on T1.Id=T2.T1_Id
GROUP BY T1.ID,T1.Name
Думайте о всей части STUFF(... FOR XML)..
как о единой функции, которая принимает в качестве аргумента один из столбцов группировки в предложении WHERE
, ищет некоторые таблицы и объединяет строковые результаты.
Это означает, что условие корреляции
WHERE TT2.T1_ID=T1.Id
может ссылаться только на столбцы группировки во внешнем запросе. Нам нужно соединение с T2, потому что мы не можем напрямую попасть в T1.ID из T3
Если вам не нужны столбцы T2, вы можете избавиться от JOIN во внешнем запросе:
select T1.Id,
T1.Name,
stuff(
(
select ','+T3.Name
from @Test3 T3
inner join @Test2 TT2 on T3.Id=TT2.T3_Id
where TT2.T1_ID=T1.Id for xml path('')
),1,1,'') as Test5
from @Test1 T1
GROUP BY T1.ID,T1.Name