我正在使用以下查询来提取日期范围的总产品价格,但是在没有销售的日子里,我还想显示日期,但值为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)
任何帮助都会很棒。
谢谢!
答案 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
?>