Совпадение нескольких столбцов в одном соединении - PullRequest
1 голос
/ 10 июля 2019

У меня есть две таблицы:

Таблица 1

item_name  |  assocID_1  |  assocID_2  |  assocID_3
ball            123           456           789

Таблица 2

assoc_key      assoc_value
123              red
456              white
789              blue

Могу ли я создать вывод:

ball    red   white  blue

Только с одним присоединением? Я понимаю, что могу просто объединить таблицы несколько раз, чтобы легко получить этот результат, но в моих реальных таблицах гораздо больше, чем 3 столбца, и приложение, которое я использую, по-видимому, поддерживает только 4 объединения на запрос.

Большое спасибо за любую помощь.

Ответы [ 3 ]

2 голосов
/ 10 июля 2019

Если вы не заботитесь о производительности, вы можете сделать:

select t1.item_name,
       max(case when t2.assoc_key = t1.assocID_1 then t2.assoc_value end),
       max(case when t2.assoc_key = t1.assocID_2 then t2.assoc_value end),
       max(case when t2.assoc_key = t1.assocID_3 then t2.assoc_value end)
from table1 t1 join
     table2 t2
     on t2.assoc_key in (t1.assocID_1, t1.assocID_2, t1.assocID_3)
group by t1.item_name;

Вы также можете использовать подзапросы. Если предположить, что в table2 есть только одна совпадающая строка:

select t1.item_name,
       (select t2.assoc_value from table2 t2 where t2.assoc_key = t1.assocID_1),
       (select t2.assoc_value from table2 t2 where t2.assoc_key = t1.assocID_2),
       (select t2.assoc_value from table2 t2 where t2.assoc_key = t1.assocID_3)
from table1 t1;

Если совпадений может быть несколько, вы можете произвольно выбрать один из них, используя функции агрегирования:

select t1.item_name,
       (select max(t2.assoc_value) from table2 t2 where t2.assoc_key = t1.assocID_1),
       (select max(t2.assoc_value) from table2 t2 where t2.assoc_key = t1.assocID_2),
       (select max(t2.assoc_value) from table2 t2 where t2.assoc_key = t1.assocID_3)
from table1 t1;
1 голос
/ 10 июля 2019

Я не думаю, что вам нужно присоединиться здесь. Вам просто нужно посмотреть, что вы можете сделать непосредственно в операторе SELECT. Вот реализация в SQL Server (В коде подготовки примера данных, если вы используете версию, более раннюю, чем SQL Server 2016, замените DROP TABLE IF EXISTS на более старый способ сделать то же самое)

DDL и данные испытаний:

DROP TABLE IF EXISTS Table1
SELECT  item_name = 'ball'
        ,assocID_1 = 123
        ,assocID_2 = 456
        ,assocID_3 = 789
INTO    Table1   

DROP TABLE IF EXISTS Table2
SELECT  assoc_key       = 123
        ,assoc_value    = 'red'
INTO    Table2
UNION ALL
SELECT  assoc_key       = 456
        ,assoc_value    = 'white'
UNION ALL
SELECT  assoc_key       = 789
        ,assoc_value    = 'blue'

SELECT * FROM Table1
SELECT * FROM Table2

1. Подход грубой силы:

SELECT  item_name   = T1.item_name
        ,(SELECT TOP 1 assoc_value FROM Table2 WHERE assoc_key = T1.assocID_1)
        ,(SELECT TOP 1 assoc_value FROM Table2 WHERE assoc_key = T1.assocID_2)
        ,(SELECT TOP 1 assoc_value FROM Table2 WHERE assoc_key = T1.assocID_3)
FROM    Table1 T1

2. Динамическое построение запроса на простоту и последующее его выполнение. При таком подходе количество столбцов не будет проблемой:

DECLARE @SQL NVARCHAR(MAX) = 'SELECT    item_name   = T1.item_name '

SELECT  @SQL += '
,(SELECT TOP 1 assoc_value FROM Table2 WHERE assoc_key = T1.'+COLUMN_NAME+')'
FROM    INFORMATION_SCHEMA.COLUMNS
WHERE   TABLE_SCHEMA = 'dbo'  -- provide your proper schema name here
AND     TABLE_NAME = 'Table1'
AND     COLUMN_NAME <> 'item_name' -- provide the columns you want to avoid doing lookups
ORDER   BY ORDINAL_POSITION

SET     @SQL+='
FROM    Table1 T1 '

PRINT   @SQL

EXEC    sp_executesql @statement=@SQL

3. Сочетание UNPIVOT, JOIN и PIVOT

SELECT  item_name, [assocID_1], [assocID_2], [assocID_3]  -- you can dynamically build the select list like above example if you need
FROM    
        (
            SELECT  IQ.item_name, IQ.assocId, T2.assoc_value
            FROM    (
                        SELECT  UNP.item_name, UNP.assocId, UNP.Value
                        FROM    Table1 T1
                        UNPIVOT
                        (
                                Value FOR assocId IN ([assocId_1], [assocId_2], [assocId_3]) -- you can dynamically build this column list like above example if you need

                        ) UNP
                    ) IQ
                    INNER JOIN Table2 T2
                        ON IQ.Value = T2.assoc_key
        ) OQ
PIVOT
(
        MAX(assoc_value)
        FOR associd IN ([assocID_1], [assocID_2], [assocID_3]) -- you can dynamically build this column list like above example if you need
) PV
0 голосов
/ 10 июля 2019
select item_name, decode(ASSOCID_1,(select assocID_1 from t1  ), (select assoc from t2 where assoc_key =aa.assocID_1),null ) ,
                                    decode(ASSOCID_2,(select assocID_2 from t1  )  , (select assoc from t2 where assoc_key =aa.assocID_1),null ),
                                    decode(ASSOCID_3,(select assocID_3 from t1  ), (select assoc from t2 where assoc_key =aa.assocID_1),null ) from t1 aa
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...