SQL Server — Объедините 3 разные таблицы, соответствующие идентификаторам этих столбцов

#sql-server #tsql

Вопрос:

Я занимаюсь этим уже несколько часов, пытаясь разобраться в этом. Поэтому мне нужно объединить значения в один столбец на основе его идентификаторов.

У меня есть 3 таблицы с именами Тип, Тип доставки и платформа. Мне нужно получить все соответствующие идентификаторы в табличной платформе и объединить все их значения в другом столбце табличной платформы.

Пример :

 Table Type           Table DeliverType                  Table Platform
----------------------------------------------------------------------------------------
ID | Type            ID    | DeliverType                ID     | TypeID  |  DeliverType
----------------------------------------------------------------------------------------
1  | TestType1        1    | DeliverType1               9      |   3     |       1
2  | TestType2        2    | DeliverType2               9      |   4     |       2
3  | TestType3        3    | DeliverType3               23     |   2     |       4
4  | TestType4        4    | DeliverType4               23     |   1     |       3

 

Это мои таблицы , я хочу вернуть имя типа, имя типа доставки и идентификатор платформы

ожидаемый результат

 Table Platform

ID | NamesConcat
9  | TestType1,TestType2,TestType3,DeliverType1,DeliverType2,9
23 | TestType2,TesType3,TestType4,DeliverType3,DeliverType4,23
 

Таким образом, у него есть только 1 идентификатор, равный 9, и все типы тестов и типы доставки, соответствующие этому идентификатору в таблице, должны быть объединены.

Вот мой код до сих пор:

 SELECT DISTINCT p.ID, 
    SUBSTRING(
        (
            SELECT ','  d.DeliverType,a.Type  AS [text()]
            FROM dbo.DeliverType d
            INNER JOIN dbo.Type a ON a.ID = p.TypeID
            ORDER BY d.ID
            FOR XML PATH ('')
        ), 2, 1000) [NamesConcat]
FROM dbo.Platform p
 

Был бы признателен за некоторую помощь в этом коллегам-программистам.

Заранее большое вам спасибо.

Ответ №1:

Из приведенных вами примеров данных я не получаю того же ожидаемого результата. Я бы ожидал результата:

Настольная Платформа

ID NamesConcat
9 Тип теста3,тип теста4,тип доставки1,тип доставки2,9
23 Тип теста1,тип теста2,тип доставки 3,тип доставки 4,23

Если это действительно ожидаемый результат и вы хотите, чтобы строки были объединены Type первым, а затем DeliverType вторым, вы можете сделать это с помощью этого запроса:

 SELECT DISTINCT pmain.ID, 
(
    SELECT t.[Type]   ',' 
    FROM Platform p 
    INNER JOIN Type t ON t.ID = p.TypeID
    WHERE p.ID = pmain.ID 
    ORDER BY t.ID
    FOR XML PATH('')
)   
(
    SELECT d.DeliverType   ','
    FROM Platform p 
    INNER JOIN DeliverType d ON d.ID = p.DeliverTypeID 
    WHERE p.ID = pmain.ID 
    ORDER BY p.ID
    FOR XML PATH('')
)   
CAST(pmain.ID AS VARCHAR(10)) AS NamesConcat
FROM Platform pmain
 

Если вам не нужны объединенные значения в таком порядке, вы можете сделать это с помощью более короткого запроса:

 SELECT DISTINCT pmain.ID, 
(
    SELECT d.DeliverType   ','   t.[Type]   ',' 
    FROM Platform p 
    INNER JOIN DeliverType d ON d.ID = p.DeliverTypeID 
    INNER JOIN Type t ON t.ID = p.TypeID
    WHERE p.ID = pmain.ID 
    FOR XML PATH('')
)   CAST(pmain.ID AS VARCHAR(10)) AS NamesConcat
FROM Platform pmain
 

Чтобы вы могли проверить работу, вот простой скрипт, который я написал, чтобы имитировать ваши демонстрационные данные и результат:

 DECLARE @Type AS TABLE (
    ID INT IDENTITY(1,1) NOT NULL, 
    [Type] VARCHAR(20) NOT NULL
);
INSERT INTO @Type([Type]) VALUES('TestType1'), ('TestType2'), ('TestType3'), ('TestType4');

DECLARE @DeliverType AS TABLE (
    ID INT IDENTITY(1, 1) NOT NULL, 
    [DeliverType] VARCHAR(25) NOT NULL
);
INSERT INTO @DeliverType([DeliverType]) VALUES ('DeliverType1'), ('DeliverType2'), ('DeliverType3'), ('DeliverType4');

DECLARE @Platform AS TABLE (
    ID INT NOT NULL, 
    TypeID INT NOT NULL, 
    DeliverTypeID INT NOT NULL
);
INSERT INTO @Platform(ID, TypeID, DeliverTypeID) VALUES (9, 3, 1), (9, 4, 2), (23, 2, 4), (23, 1, 3);

SELECT DISTINCT pmain.ID, 
(
    SELECT d.DeliverType   ','   t.[Type]   ',' 
    FROM @Platform p 
    INNER JOIN @DeliverType d ON d.ID = p.DeliverTypeID 
    INNER JOIN @Type t ON t.ID = p.TypeID
    WHERE p.ID = pmain.ID 
    FOR XML PATH('')
)   CAST(pmain.ID AS VARCHAR(10)) AS NamesConcat
FROM @Platform pmain

SELECT DISTINCT pmain.ID, 
(
    SELECT t.[Type]   ',' 
    FROM @Platform p 
    INNER JOIN @Type t ON t.ID = p.TypeID
    WHERE p.ID = pmain.ID 
    ORDER BY t.ID
    FOR XML PATH('')
)   
(
    SELECT d.DeliverType   ','
    FROM @Platform p 
    INNER JOIN @DeliverType d ON d.ID = p.DeliverTypeID 
    WHERE p.ID = pmain.ID 
    ORDER BY p.ID
    FOR XML PATH('')
)   
CAST(pmain.ID AS VARCHAR(10)) AS NamesConcat
FROM @Platform pmain
 

Я надеюсь, что это то, что вы искали!

Комментарии:

1. Ты-спаситель. Большое спасибо. Не могли бы вы, пожалуйста, объяснить различия между pmain и p? Остальную часть кода я понял прекрасно.

2. Конечно! Поскольку мы присоединяемся к подзапросу, платформа таблицы используется дважды. Мы должны создать псевдоним таблицы, чтобы SQL Server (или любая другая СУБД) не запуталась. Я называю самый внешний псевдоним pmain (не творческий, но он у вас есть — таблица платформы в основном запросе). В подзапросах я использую псевдоним p (очень ленивый, я знаю…). Когда я соединяю основной запрос с подзапросом, я хочу сопоставить основное значение идентификатора с платформы (pmain. ИДЕНТИФИКАТОР) к идентификатору платформы в подзапросе (p.ID).

3. О , теперь я все понял! Большое тебе спасибо , чувак, ты действительно спаситель.