Есть запрос к базе, который собирает информацию для отображения статистики по заказам.
Структура БД
В запросе используются таблицы:
- order – заказы:
- status – признак оплаты (3 – "оплачен", для оплачиваемых заказов, 2 – "принят", для неоплачиваемых заказов),
- payment_type – тип оплаты (card/cash – картой/наличкой; omc, dmc, free – "неоплачиваемый")
- order_services – услуги в заказах ("слепок" с кодом, ценой и названием услуги),
- lpu_services – перечень услуг (фактический прайс-лист),
- lpu_service_categories – категории услуг.
Можно ли как-то оптимизировать этот запрос ?
SELECT
os.order_id,
count(os.id) total_count,
SUM(IF((o.`payment_type`='cash' or o.`payment_type`='card'), os.price, 0)) paid_revenue,
SUM(IF((o.`payment_type`='dmc'), os.price, 0)) dmc_revenue,
SUM(IF(o.`payment_type`='cash', 1, 0)) cash_count,
SUM(IF(o.`payment_type`='card', 1, 0)) card_count,
SUM(IF(o.`payment_type`='omc', 1, 0)) oms_count,
SUM(IF(o.`payment_type`='free', 1, 0)) free_count,
SUM(IF(o.`payment_type`='dmc', 1, 0)) dmc_count,
SUM(lsc.id=1) usg_count,
SUM(IF(lsc.id=1 AND o.`payment_type`='omc', 1, 0)) usg_oms_count,
SUM(IF(lsc.id=1 AND (o.`payment_type`='omc'), os.price, 0)) usg_oms_revenue,
SUM(IF(lsc.id=1 AND o.`payment_type`='dmc', 1, 0)) usg_dms_count,
SUM(IF(lsc.id=1 AND (o.`payment_type`='dmc'), os.price, 0)) usg_dms_revenue,
SUM(IF(lsc.id=1 AND o.`payment_type`='free', 1, 0)) usg_free_count,
SUM(IF(lsc.id=1 AND (o.`payment_type`='cash' OR o.`payment_type`='card'), 1, 0)) usg_paid_count,
SUM(IF(lsc.id=1 AND (o.`payment_type`='cash' OR o.`payment_type`='card'), os.price, 0)) usg_paid_revenue,
SUM(lsc.id=2) md_count,
SUM(IF(lsc.id=2 AND o.`payment_type`='omc', 1, 0)) md_oms_count,
SUM(IF(lsc.id=2 and o.`payment_type`='omc', 2.16, 0)) md_oms_revenue,
SUM(IF(lsc.id=2 AND o.`payment_type`='dmc', 1, 0)) md_dms_count,
SUM(IF(lsc.id=2 AND (o.`payment_type`='dmc'), os.price, 0)) md_dms_revenue,
SUM(IF(lsc.id=2 AND o.`payment_type`='free', 1, 0)) md_free_count,
SUM(IF(lsc.id=2 AND (o.`payment_type`='cash' OR o.`payment_type`='card'), 1, 0)) md_paid_count,
SUM(IF(lsc.id=2 AND (o.`payment_type`='cash' OR o.`payment_type`='card'), os.price, 0)) md_paid_revenue,
SUM(lsc.id=7) fizio_count,
SUM(IF(lsc.id=7 AND o.`payment_type`='omc', 1, 0)) fizio_oms_count,
SUM(IF(lsc.id=7 AND (o.`payment_type`='omc'), os.price, 0)) fizio_oms_revenue,
SUM(IF(lsc.id=7 AND o.`payment_type`='dmc', 1, 0)) fizio_dms_count,
SUM(IF(lsc.id=7 AND (o.`payment_type`='dmc'), os.price, 0)) fizio_dms_revenue,
SUM(IF(lsc.id=7 AND o.`payment_type`='free', 1, 0)) fizio_free_count,
SUM(IF(lsc.id=7 AND (o.`payment_type`='cash' OR o.`payment_type`='card'), 1, 0)) fizio_paid_count,
SUM(IF(lsc.id=7 AND (o.`payment_type`='cash' OR o.`payment_type`='card'), os.price, 0)) fizio_paid_revenue,
SUM(lsc.id=8) massage_count,
SUM(IF(lsc.id=8 AND o.`payment_type`='omc', 1, 0)) massage_oms_count,
SUM(IF(lsc.id=8 AND (o.`payment_type`='omc'), os.price, 0)) massage_oms_revenue,
SUM(IF(lsc.id=8 AND o.`payment_type`='dmc', 1, 0)) massage_dms_count,
SUM(IF(lsc.id=8 AND (o.`payment_type`='dmc'), os.price, 0)) massage_dms_revenue,
SUM(IF(lsc.id=8 AND o.`payment_type`='free', 1, 0)) massage_free_count,
SUM(IF(lsc.id=8 AND (o.`payment_type`='cash' OR o.`payment_type`='card'), 1, 0)) massage_paid_count,
SUM(IF(lsc.id=8 AND (o.`payment_type`='cash' OR o.`payment_type`='card'), os.price, 0)) massage_paid_revenue,
SUM(lsc.id=9) medproc_count,
SUM(IF(lsc.id=9 AND o.`payment_type`='omc', 1, 0)) medproc_oms_count,
SUM(IF(lsc.id=9 AND (o.`payment_type`='omc'), os.price, 0)) medproc_oms_revenue,
SUM(IF(lsc.id=9 AND o.`payment_type`='dmc', 1, 0)) medproc_dms_count,
SUM(IF(lsc.id=9 AND (o.`payment_type`='dmc'), os.price, 0)) medproc_dms_revenue,
SUM(IF(lsc.id=9 AND o.`payment_type`='free', 1, 0)) medproc_free_count,
SUM(IF(lsc.id=9 AND (o.`payment_type`='cash' OR o.`payment_type`='card'), 1, 0)) medproc_paid_count,
SUM(IF(lsc.id=9 AND (o.`payment_type`='cash' OR o.`payment_type`='card'), os.price, 0)) medproc_paid_revenue,
SUM(lsc.id=10) fd_count,
SUM(IF(lsc.id=10 AND o.`payment_type`='omc', 1, 0)) fd_oms_count,
SUM(IF(lsc.id=10 AND (o.`payment_type`='omc'), os.price, 0)) fd_oms_revenue,
SUM(IF(lsc.id=10 AND o.`payment_type`='dmc', 1, 0)) fd_dms_count,
SUM(IF(lsc.id=10 AND (o.`payment_type`='dmc'), os.price, 0)) fd_dms_revenue,
SUM(IF(lsc.id=10 AND o.`payment_type`='free', 1, 0)) fd_free_count,
SUM(IF(lsc.id=10 AND (o.`payment_type`='cash' OR o.`payment_type`='card'), 1, 0)) fd_paid_count,
SUM(IF(lsc.id=10 AND (o.`payment_type`='cash' OR o.`payment_type`='card'), os.price, 0)) fd_paid_revenue
FROM order_services os, lpu_services ls, lpu_service_categories lsc, `order` o
WHERE
o.id=os.order_id AND os.service_id=ls.id AND ls.service_category_id=lsc.id
AND (
((o.`payment_type`='cash' or o.`payment_type`='card') and o.`status`=3)
OR (o.`payment_type`='omc' AND o.`status`=2)
OR (o.`payment_type`='dmc' AND o.`status`=2)
OR (o.`payment_type`='free' AND o.`status`=2)
)
GROUP BY order_id
ORDER BY `os`.`order_id` ASC
UPD1.: Вопрос, скорее всего, касается синтаксиса. Такое ощущение, что можно сгруппировать параметры в select'е, т.к. много кусков повторяются. Но как это сделать пока не могу придумать.