Сложный запрос фильтрации выручки по типам оплаты

Помогите, пожалуйста, с задачей. Нужно сделать фильтрацию выручки по типам оплаты. Выручка считается по чекам в таблице 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;

Ответы (0 шт):