使用日历表填写日期范围查询中缺少的空白

时间:2011-10-17 16:02:07

标签: php mysql

我正在使用以下查询来提取日期范围的总产品价格,但是在没有销售的日子里,我还想显示日期,但值为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)

任何帮助都会很棒。

谢谢!

2 个答案:

答案 0 :(得分:2)

您需要在日历表上使用外部联接。像

这样的东西
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语句。)

答案 1 :(得分:0)

也许这段代码可以提供帮助,而不是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('Y-m-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('Y-m-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('Y-m-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

?>