Соедините 2 таблицы «многие ко многим» и получите 3 смежных логических столбца - PullRequest
1 голос
/ 11 апреля 2020

Допустим, есть три таблицы A, B и C, где

Таблица A:

╔═══════╗
║ col_1 ║
╠═══════╣
║ a     ║
║ b     ║
║ c     ║
╚═══════╝

Таблица B:

╔═══════╗
║ col_2 ║
╠═══════╣
║ o     ║
║ p     ║
║ q     ║
╚═══════╝

Таблица C - это:

╔═══════╗
║ c_col ║
╠═══════╣
║ x     ║
║ y     ║
║ z     ║
╚═══════╝

Допустим, существует связь «многие ко многим» между таблицей A и таблицей C через таблицу сопоставления A_to_C, показанную ниже:

╔═══════╦═══════╗
║ col_1 ║ c_col ║
╠═══════╬═══════╣
║ a     ║ x     ║
║ a     ║ y     ║
║ b     ║ y     ║
║ b     ║ z     ║
║ c     ║ x     ║
╚═══════╩═══════╝

Кроме того, существует связь «многие ко многим» между таблицей B и таблицей C через таблицу отображения B_to_C, показанную ниже:

╔═══════╦═══════╗
║ col_2 ║ c_col ║
╠═══════╬═══════╣
║ o     ║ y     ║
║ o     ║ z     ║
║ p     ║ x     ║
║ q     ║ x     ║
║ q     ║ y     ║
╚═══════╩═══════╝

Для значения 'b' in col_1 и значение 'q' в col_2 Мне нужно получить результат как:

╔═══════╦═══════╦════════╗
║ c_col ║ col_1 ║ col_2  ║
╠═══════╬═══════╬════════╣
║ x     ║ NULL  ║ q      ║
║ y     ║ b     ║ q      ║
║ z     ║ b     ║ NULL   ║
╚═══════╩═══════╩════════╝

, который позже можно преобразовать в:

╔═══════╦═══════╦═══════╗
║ c_col ║ col_1 ║ col_2 ║
╠═══════╬═══════╬═══════╣
║ x     ║ False ║ True  ║
║ y     ║ True  ║ True  ║
║ z     ║ True  ║ False ║
╚═══════╩═══════╩═══════╝

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

Ответы [ 3 ]

2 голосов
/ 11 апреля 2020

Вы можете использовать следующий запрос:

select c.c_col, ac.col_1 is not null, bc.col_2 is not null
from C c
left join (select * from A_to_C where col_1 = 'b') ac on c.c_col = ac.c_col
left join (select * from B_to_C where col_2 = 'b') bc on c.c_col = bc.c_col
where (ac.col_1, bc.col2) = ('b', 'q')
2 голосов
/ 11 апреля 2020

Вам не нужны две ЛЕВЫЕ СОЕДИНЕНИЯ, а НЕ НУЛЬ; EXISTS() уже дает логическое значение:


SELECT C.c_col
        , EXISTS( SELECT *
                FROM A_to_C ac
                WHERE ac.c_col = C.c_col AND ac.col_1 = 'b'
                ) AS col_1
        , EXISTS( SELECT *
                FROM B_to_C bc
                WHERE bc.c_col = C.c_col AND bc.col_2 = 'q'
                ) AS col_2
FROM C
        ;
1 голос
/ 11 апреля 2020

Вы можете сгенерировать этот результат с серией LEFT JOIN s, поместив фильтры col_1 и col_2 в условия JOIN:

SELECT C.c_col, ac.col_1, bc.col_2
FROM C
LEFT JOIN A_to_C ac ON ac.c_col = C.c_col AND ac.col_1 = 'b'
LEFT JOIN B_to_C bc ON bc.c_col = C.c_col AND bc.col_2 = 'q'

Вывод:

c_col   col_1   col_2
x       (null)  q
y       b       q
z       b       (null)

Демонстрация по SQLFiddle

Затем эти значения можно преобразовать в логические значения, проверяя, что они не NULL:

SELECT C.c_col, ac.col_1 IS NOT NULL AS col_1, bc.col_2 IS NOT NULL AS col_2
FROM C
LEFT JOIN A_to_C ac ON ac.c_col = C.c_col AND ac.col_1 = 'b'
LEFT JOIN B_to_C bc ON bc.c_col = C.c_col AND bc.col_2 = 'q'

Вывод:

c_col   col_1   col_2
x       false   true
y       true    true
z       true    false

Демонстрация по SQLFiddle

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...