#sql #sql-server #tsql #sql-server-2014
#sql #sql-сервер #tsql #sql-сервер-2014 #sql-server-2014
Вопрос:
Мои таблицы
MyTable
---- ------- ---------------
| Id | Title | DependencyIds |
---- ------- ---------------
DependentIds
содержит такие значения, как 14;77;120
.
MyDependentTable
-------------- ------
| DependencyId | Name |
-------------- ------
Предыстория
Я должен выбирать данные из MyTable
каждой зависимости MyDependentTable
, разделенной запятой.
Ожидаемый результат:
--------- -------------------------------------
| Title | Dependencies |
--------- -------------------------------------
| Test | ABC, One-two-three, Some Dependency |
--------- -------------------------------------
| Example | ABC |
--------- -------------------------------------
Мой запрос
SELECT t.Title,
(SELECT ISNULL((
SELECT DISTINCT
(
SELECT dt.Name '',
CASE WHEN DependencyIds LIKE '%;%' THEN ', ' ELSE '' END AS [text()]
FROM MyDependentTable dt
WHERE dt.DependencyId IN (SELECT Value FROM dbo.fSplitIds(t.DependencyIds, ';'))
ORDER BY dt.DependencyId
FOR XML PATH('')
)), '')) Dependencies
FROM dbo.MyTable t
Описание проблемы
Запрос работает, но добавляет дополнительную запятую при наличии нескольких зависимостей:
--------- ---------------------------------------
| Title | Dependencies |
--------- ---------------------------------------
| Test | ABC, One-two-three, Some Dependency, |
--------- ---------------------------------------
| Example | ABC |
--------- ---------------------------------------
Я не могу использовать SUBSTRING(ISNULL(...
, потому что я не могу получить доступ к длине строки и, следовательно, я не могу установить длину SUBSTRING
.
Есть ли какая-нибудь возможность избавиться от этой ненужной дополнительной запятой?
Ответ №1:
Обычно для объединения групп в Sql Server люди добавляют начальную запятую и удаляют ее с помощью STUFF
функции, но даже это выглядит некрасиво.
Outer Apply
метод выглядит аккуратно, чтобы сделать это вместо correlated sub-query
. В этом методе нам не нужно завершать SELECT
запрос с ISNULL
помощью или STUFF
SELECT DISTINCT t.title,
Isnull(LEFT(dependencies, Len(dependencies) - 1), '')
Dependencies
FROM dbo.mytable t
OUTER apply (SELECT dt.NAME ','
FROM mydependenttable dt
WHERE dt.dependencyid IN (SELECT value
FROM
dbo.Fsplitids(t.dependencyids,';'))
ORDER BY dt.dependencyid
FOR xml path('')) ou (dependencies)
Ответ №2:
Вот метод, использующий STUFF
.
SELECT t.Title
,STUFF((SELECT ', ' CAST(dt.Name AS VARCHAR(10)) [text()]
FROM MyDependentTable dt
WHERE dt.DependencyId IN (SELECT Value FROM dbo.fSplitIds(t.DependencyIds, ';'))
ORDER BY dt.DependencyId
FOR XML PATH(''), TYPE).value('.','NVARCHAR(MAX)'),1,2,' ') Dependencies
FROM dbo.MyTable t