Сложный запрос фильтрации выручки по типам оплаты
Помогите, пожалуйста, с задачей. Нужно сделать фильтрацию выручки по типам оплаты. Выручка считается по чекам в таблице check. С чеками связаны транзакции, в которых хранится информация об оплате (также стоимость чека хранится в самом чеке). Транзакции могут быть разных типов (наличные, безналичные и так далее). Транзакции хранятся в таблице pay_transaction, тип транзакции - в таблице payment_type. Считать выручку мешают смешанные чеки. Смешанные чеки - это чеки, оплаченные несколькими видами оплаты. Например, наличными и безналичными. Для таких чеков создаются несколько транзакций разных типов. Чтобы определить тип чека (смешанный или простой) я считаю количество транзакций разных типов. Если это число больше, то чек смешанный. Но смешанных чеков в природе не существует. Это просто чеки, оплаченные разными видами оплаты. И наличная и безналичная части этого чека должны идти в соответствующие категории выручки (в категорий налички или безналичного расчета). Как это можно сделать?
Я придумал для простых чеков считать выручку на основании полей check.total_with_discount и check.total. Это правильно. Но со смешанными чеками все сложнее. При подсчете, например, выручки наличными, нельзя просто взять и прибавить стоимость смешанного чека, потому что она общая. Нужно взять из транзакции нужного типа (наличка) количество оплаты и присуммировать к общей выручке.
Как это можно реализовать? Я уже запутался. Логика сложная. Мешает то, что при джойне таблиц с транзакциями строки с чеками дублируются и их приходится группировать, чтобы удалить дубликаты. С агрегаций и группировкой в этой запросе вообще проблемы.
Запрос выглядит так:
with all_checks as (
select c.id as id,
count(distinct pt.id) > 1 as mixed,
sum(tx.sum) as tx_sum
from `check` c
join pay_transaction tx on c.id = tx.order_check_id
join payment_type pt on tx.type_id = pt.id
join posinfo pi on c.id_pos = pi.id
where c.status = 7
and c.id_pos = 745
and id_brand = 24
and c.time between '2024-12-01 00:00:00' and '2024-12-01 23:59:59'
and pt.name_type = 'Наличные'
group by c.id
)
SELECT SUM(IF(t.mixed = false, IF(t.total_with_sale != 0, t.total_with_sale, t.total), t.tx_sum)) as total
FROM (
SELECT total_with_sale, total, mixed, tx_sum
FROM `check` c
JOIN all_checks ac on c.id = ac.id
join pay_transaction tx on c.id = tx.order_check_id
join payment_type pt on tx.type_id = pt.id
WHERE pt.name_type = 'Наличные'
GROUP BY c.id
) as t;