Заполнение пробелов в запросе диапазона дат с использованием таблицы календаря

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

Я создал таблицу календаря с большим диапазоном дат, но не смог разработать лучший способ сделать это, все, что я делаю, просто пропускает дни без продаж.

Ниже приведен запрос, который я использую (без таблицы календаря):

SELECT DATE_FORMAT(b.purchase_date, '%d %b %Y') as date, sum(price) as price FROM order_products a INNER JOIN order_saved b ON a.order_id = b.id WHERE b.purchase_date BETWEEN '2011-09-16 23:59' AND '2011-10-16 23:59' AND b.status > 2 AND a.usr_id = 'XXXX' GROUP BY DAY(b.purchase_date) ORDER BY b.purchase_date ASC 

Календарная таблица, которую я пробовал, просто содержит список диапазонов дат, начиная с 2010-01-01 до 2014-12-30 (calendar.date – table.row)

Любая помощь будет потрясающей.

Благодаря!

Вам нужно внешнее соединение в таблице календаря. Что-то вроде

 SELECT c.cal_date, coalesce(t1.price, 0) as total FROM calendar c LEFT JOIN (SELECT b.purchase_date::date, sum(price) as price FROM order_products a INNER JOIN order_saved b ON a.order_id = b.id AND b.purchase_date BETWEEN '2011-09-16 23:59' AND '2011-10-16 23:59' AND b.status > 2 AND a.usr_id = 'XXXX' GROUP BY b.purchase_date) t1 on t1.purchase_date = c.cal_date WHERE cal_date BETWEEN '2011-09-16 23:59' AND '2011-10-16 23:59' ORDER BY c.cal_date 

Вы получите лучшие ответы, если вы опубликуете заявления DDL ( CREATE TABLE ) и минимальные INSERT которые дают нам достаточно данных для фактического тестирования наших ответов. (Измените свой вопрос и вставьте операторы DDL и INSERT.)

Возможно, этот код может помочь, вместо того, чтобы epxlaining здесь разместили комментарий там, где это необходимо. Он принимает массив (предположим, что он исходит из db) и заменяет отсутствующие даты:

 <?php $sales=Array('2011-09-16 23:59'=>2,'2011-09-17 23:59'=>7, '2011-09-18 23:59'=>7,'2011-09-19 23:59'=>7,'2011-09-20 23:59'=>7, '2011-09-21 23:59'=>7,'2011-09-22 23:59'=>7,'2011-09-23 23:59'=>1, '2011-10-05 23:59'=>4,'2011-10-21 23:59'=>16,'2012-04-22 23:59'=>12); $no_sale=' | <font color=red>0</font><br>'; //initialize the previosly printed date to the previous of the very first date in $sales $last_printed = date('Ym-d', strtotime(substr(key($sales),0,10) . " -1 Day")) ; foreach($sales as $cd => $sales_cnt) { //extract current date $cd = substr($cd,0,10); //get the next day of the last date that was echoed $next_of_last_printed = date('Ym-d', strtotime($last_printed . " +1 Day")); //if the current date retrieved from database is next of the last printed if($next_of_last_printed == $cd) { echo $cd.' | ', $sales_cnt,'<br>';//then print it $last_printed=$cd;//since we print it change the last printed }//if else { //since current retrieved from db is not valid print a valid date echo $next_of_last_printed ,$no_sale; $last_printed = $next_of_last_printed;//since we printed a date set last printed while(true) { //since we set the last printed then get the next of it $next_of_last_printed = date('Ym-d', strtotime($last_printed . " +1 Day")); //if the next we generated is the same with the one retrieved from db if($next_of_last_printed ==$cd) { echo $cd.' | ', $sales_cnt,'<br>';//then echo this retrieved from db $last_printed = $cd;//since we printed a date set last printed break(1); } //since we got the next date print it echo $next_of_last_printed,$no_sale; $last_printed = $next_of_last_printed; //then set last printed }//while }//else }//foreach ?> в <?php $sales=Array('2011-09-16 23:59'=>2,'2011-09-17 23:59'=>7, '2011-09-18 23:59'=>7,'2011-09-19 23:59'=>7,'2011-09-20 23:59'=>7, '2011-09-21 23:59'=>7,'2011-09-22 23:59'=>7,'2011-09-23 23:59'=>1, '2011-10-05 23:59'=>4,'2011-10-21 23:59'=>16,'2012-04-22 23:59'=>12); $no_sale=' | <font color=red>0</font><br>'; //initialize the previosly printed date to the previous of the very first date in $sales $last_printed = date('Ym-d', strtotime(substr(key($sales),0,10) . " -1 Day")) ; foreach($sales as $cd => $sales_cnt) { //extract current date $cd = substr($cd,0,10); //get the next day of the last date that was echoed $next_of_last_printed = date('Ym-d', strtotime($last_printed . " +1 Day")); //if the current date retrieved from database is next of the last printed if($next_of_last_printed == $cd) { echo $cd.' | ', $sales_cnt,'<br>';//then print it $last_printed=$cd;//since we print it change the last printed }//if else { //since current retrieved from db is not valid print a valid date echo $next_of_last_printed ,$no_sale; $last_printed = $next_of_last_printed;//since we printed a date set last printed while(true) { //since we set the last printed then get the next of it $next_of_last_printed = date('Ym-d', strtotime($last_printed . " +1 Day")); //if the next we generated is the same with the one retrieved from db if($next_of_last_printed ==$cd) { echo $cd.' | ', $sales_cnt,'<br>';//then echo this retrieved from db $last_printed = $cd;//since we printed a date set last printed break(1); } //since we got the next date print it echo $next_of_last_printed,$no_sale; $last_printed = $next_of_last_printed; //then set last printed }//while }//else }//foreach ?>