Объединение с агрегатной функцией в пустом наборе результатов

#mysql

#mysql

Вопрос:

У меня есть требование получить значения sum, avg, count как 0 после имени учреждения, когда дата lr.processed_on не совпадает с датой ввода. как я могу добиться этого в следующем запросе

 SELECT bd.id as institutionId,  bd.institution_name as institution,  count(lr.id) as numberOfTransaction,  sum(lr.amount) as totalTransactionAmount,  avg(lr.amount) as averageTransactionAmount,  sum(lr.processing_fee) as totalProcessingFee from daily_transaction lr  join  (  select s.id  from status s  where s.name not in (:statusName)) s on  lr.customer_status = s.id  join account sa on lr.account = sa.id  join branch b on sa.branch = b.id  right join institution_details bd on b.institution = bd.id  join status s2 on bd.status = s2.id where (:institutionIdParam is null or bd.id = :institutionIdParam)    and (:instutionStatus is null  or s2.description = :instutionStatus)  and (:fromDate is null  and :toDate is null or cast(lr.processed_on as date) lt;= :toDate  and cast(lr.processed_on as date) gt;= :fromDate) group by bd.id , bd.institution_name order by bd.institution_name asc;  

Комментарии:

1. Можете ли вы поместить в свой пост образцы входных и выходных данных, чтобы лучше понять вопрос?

2. если я помещу ввод, который не является lr.обработанным, то вывод будет пустым, но я хочу получить результат в виде 0 транзакций для всех деталей в выводе

Ответ №1:

Цель использования RIGHT JOIN для institution_details, по-видимому, состоит в том, чтобы вы хотели, чтобы все учреждения были перечислены независимо от их ежедневных транзакций. Для тех учреждений, где нет ежедневных транзакций, processed_on рассматривается как имеющий НУЛЕВОЕ значение (именно так будет вести себя правильное соединение), и условие WHERE, подобное вашему, вернет значение false, а затем отфильтруются данные institution_details.

Вы можете преодолеть это, переместив предложение проверки параметров в условие соединения, например так:

 right join   institution_details bd on  b.institution = bd.id  and   ((:fromDate is null and :toDate is null)   or   (cast(lr.processed_on as date) lt;= :toDate and cast(lr.processed_on as date) gt;= :fromDate))  

и убираем его из пункта «ГДЕ«.

Обратите внимание на скобки, которые я добавил в ваше выражение; в присутствии операторов OR и AND нам необходимо учитывать приоритет операторов и порядок вычисления, было бы неправильно (на мой взгляд) не иметь этих скобок. Даже при этом вам необходимо предотвратить ситуацию, когда предоставляется только один (но не оба) параметра :FromDate и :ToDate.