Условное СОЕДИНЕНИЕ на основе значения столбца

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

Таблица TRANSACTIONS содержит столбцы CATID и BILLID, которые относятся к первичным ключам в таблицах SECONDARYCATEGORIES и BILLS. Обе таблицы TRANSACTIONS и BILLS имеют столбец PCATID, который ссылается на первичный ключ в таблице PRIMARYCATEGORIES.

Я создаю SQL-запрос, который суммирует столбец «сумма» в таблице TRANSACTIONS и возвращает первичный ключ из PCATID и сумму из всех записей, связанных с этим значением. Если BILLID установлено в -1, он должен найти PCATID в SECONDARYCATEGORIES, где SECONDARYCATEGORIES.ID = TRANSACTIONS.CATID, в противном случае (поскольку -1 указывает, что это НЕ счет), он должен найти PCATID из записи BILL, где BILLS.ID соответствует TRANSACTIONS.BILLID.

Я ищу что-то вроде этого (очевидно, недействительный SQL):

SELECT
 SECONDARYCATEGORIES.PCATID,
 SUM(TRANSACTIONS.AMOUNT)
FROM
 TRANSACTIONS
IF (BILLID = -1) JOIN SECONDARYCATEGORIES ON SECONDARYCATEGORIES.ID = TRANSACTIONS.CATID
ELSE JOIN SECONDARYCATEGORIES ON SECONDARYCATEGORIES.ID = BILLS.CATID WHERE BILLS.ID = TRANSACTIONS.BILLID

Я пробовал множество различных JOIN, операторов IF и т. д., и я просто не могу заставить эту работу работать. Я думал разбить это на разные SQL-запросы на основе значения BILLID и суммировать значения, но мне бы очень хотелось сделать все это в одном SQL-запросе, если это возможно.

Я знаю, что здесь не хватает чего-то очевидного; любая помощь очень ценится.

Редактировать: я забыл описать таблицу BILLS. Он содержит основную категорию, идентификатор, а также некоторые описательные данные.


person cameron    schedule 20.12.2017    source источник
comment
два левых внешних соединения должны решить вашу проблему здесь. однако ваша таблица BILLS отсутствует   -  person maSTAShuFu    schedule 20.12.2017
comment
Я не вижу здесь таблицы BILLS.   -  person Eric    schedule 20.12.2017
comment
Можете ли вы предоставить некоторые образцы данных и ожидаемый результат?   -  person digital.aaron    schedule 20.12.2017


Ответы (3)


Вы можете использовать OR в своем JOIN, например:

SELECT S.PCATID,
       SUM(T.AMOUNT)
FROM TRANSACTIONS T 
LEFT JOIN BILLS ON BILLS.ID = T.BILLID 
JOIN SECONDARYCATEGORIES S ON (S.ID = T.CATID AND T.BILLID = -1)
                           OR (S.ID = BILLS.CATID AND BILLS.ID = T.BILLID)
person Aaron Dietz    schedule 20.12.2017
comment
Это именно то, что я искал. Почему-то у меня сложилось впечатление, что И/ИЛИ не разрешено в части ON JOIN. Большое спасибо за помощь. - person cameron; 20.12.2017
comment
Каково влияние таких условных соединений на производительность? Есть ли альтернативный способ не принимать все решения в условиях JOIN? - person SwapSays; 30.04.2021

Вы также можете использовать COALESCE и CASE в своих JOIN.

SELECT ID = COALESCE(s.PCATID,b.PCATID)
    ,Total = SUM(t.AMOUNT)
FROM TRANSACTIONS t
LEFT JOIN BILLS b ON b.BILLID = CASE WHEN t.BILLID <> -1 THEN t.BILLID END
LEFT JOIN SECONDARYCATEGORIES s ON s.CATID = CASE WHEN t.BILLID = -1 THEN t.CATID END
GROUP BY COALESCE(s.PCATID,b.BILLID) 
person digital.aaron    schedule 20.12.2017
comment
Это не условное соединение. Это делает соединения безоговорочно, а затем выбирает одно значение или другое. Это не эффективно. - person Quolonel Questions; 28.02.2020
comment
@QuolonelQuestions на самом деле, если вы сравните план выполнения, сгенерированный моим запросом, и план, сгенерированный запросом принятого ответа, вы обнаружите, что они почти идентичны, за исключением пары дополнительных Compute Scalar в моем плане. Мое решение не более неэффективно, чем включение OR в предложение соединения. - person digital.aaron; 29.02.2020

Я использую UNION для выбора любого запроса. Но второй запрос, очевидно, не будет работать, потому что в нем отсутствует таблица BILLS.

SELECT SECONDARYCATEGORIES.PCATID
    , SUM(TRANSACTIONS.AMOUNT)
FROM TRANSACTIONS
JOIN SECONDARYCATEGORIES ON SECONDARYCATEGORIES.ID = TRANSACTIONS.CATID AND BILLID = -1
UNION
SELECT SECONDARYCATEGORIES.PCATID
    , SUM(TRANSACTIONS.AMOUNT)
FROM TRANSACTIONS
JOIN SECONDARYCATEGORIES ON SECONDARYCATEGORIES.ID = BILLS.CATID AND BILLID <> -1
WHERE BILLS.ID = TRANSACTIONS.BILLID
person Eric    schedule 20.12.2017