Хотя в качестве примера, ваше предложение WHERE в основном возвращает ВСЕХ пациентов.Вероятно, что убивает вашу производительность, так это то, что вы делаете 3 коррелированных запроса в своих списках полей, каждый раз запрашивая у каждого человека.Один раз для счета-фактуры и два раза для платежей.
Вместо этого я реструктурировал запрос на основе предварительных запросов LEFT-JOINS в таблицы счетов-фактур и платежей.Если вы посмотрите, таблица счетов-фактур предварительно суммируется с GROUP BY каждого идентификатора пациента.Аналогично по таблице платежей GROUP BY каждого пациента.Таким образом, в худшем случае каждый подзапрос будет возвращать по САМОЙ одной записи для данного пациента с суммой всех счетов и соответствующих скидок.Для платежей - сумма всех платежей и самая последняя дата.
Итак, начиная с таблицы пациентов, я могу присоединиться к общему идентификатору пациента, чтобы увидеть упрощенные итоговые значения до окончательной.выход и будет применим для всех пациентов.Да, вы все равно можете добавить критерии WHERE для дальнейшего ограничения, но это должно работать значительно лучше.
SELECT
p.patientid,
p.firstname,
p.lastname,
p.mobilephone,
p.email,
coalesce( PatInv.JustSumOfAmount - PatInv.DiscountedAmounts, 0 )
- coalesce( PatPay.PaidAmounts, 0 ) Answer,
case when PatPay.PatientID IS NULL
then ' '
else Date_format( PatPay.LastPaymentDate, '%d-%m-%Y') end lastpaymentdate
FROM
patient p
LEFT JOIN
( select
i.patientID,
sum( i.ammount ) justSumOfAmount,
sum( i.ammount * ( discount / 100 )) as discountedAmounts
from
invoice i
where
i.invoicedNumber > 0
group by
i.patientID
order by
i.patientid ) PatInv
on p.patientid = patInv.patientID
LEFT JOIN
( SELECT
pay.patientID,
Sum(pay.ammount) paidAmounts,
max( pay.paymentDate ) LastPaymentDate
FROM
payment pay
group by
pay.patientID
order by
pay.patientid ) PatPay
on p.patientID = patPay.PatientID
Я разместил этот запрос на SQL Fiddle Кроме того, просматривая ваши таблицы, вашиТаблицы счетов-фактур и платежей ДОЛЖНЫ КАЖДЫЙ иметь индекс идентификатора пациента, чтобы помочь оптимизировать запросы.Я не знаю, был ли это пример недосмотра с вашего sql-fiddle против производства, но это также повлияло бы на производительность.
Опция SQLFiddle, которую я имею, занимает 5 мс против ваших 2-3 мс, но этотолько для нескольких предоставленных записей.Могу поспорить, что против ваших 1000+ пациентов и 1000 транзакций в каждом счете и таблице платежей это сделает этот вариант запроса быстрее, чем коррелированные запросы.
Думайте о своем запросе как об этом.У меня 1000 пациентов.Запросите таблицу счетов 1000 раз, запросите таблицу платежей 2000 раз (1000 для суммы платежей, еще 1000 раз для самой последней даты для каждого пациента).
Мой запрос - один раз запросите таблицу счетов и суммируйте1 запись на пациента.Предварительно запросите таблицу платежей и суммируйте 1 запись на пациента.Присоедините пациентов к этим двум таблицам напрямую по ID.