2017-03-24 75 views
1

我目前正在尝试获取过去30天的所有订单,并返回总数和订单数。如果一天没有订单,我仍然需要在结果中显示一行(显然计数和总计== 0)。选择和计算过去30天的所有订单

有没有办法做到这一点?

有很多问题要求不需要总是获得30行。但是,我不能评论他们,因为我的声誉太低。

例如: selecting all orders for last 30 days, and counting how many per day

+3

如何是你的数据库结构? –

+0

你真的需要这样做吗?如果处理结果的代码不在SQL中,它不知道它是否为零? –

+0

如果你真的想在SQL中完成所有这些,这听起来像是一个存储过程的工作。 sproc会创建一个临时表,您可以在其中插入30条记录(每天1条记录),然后返回并更新每个日期的订单总计。这会让你在结果集中始终有30天的期望输出 – mituw16

回答

3

天发电机就是从这里generate days from date range

采取的另一项工作是简单的左加入到分组的订单

(左与表和列名称的变化联接子查询)

select a.Date, pr.orders_count, pr.price 
from (
    select curdate() - INTERVAL (a.a + (10 * b.a) + (100 * c.a)) DAY as Date 
    from (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a 
    cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b 
    cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as c 
) a 
left join (select order_time, count(*) as orders_count, sum(price) as price from orders group by order_time) pr 
on a.Date = pr.order_time 
where a.Date >= NOW() - INTERVAL 30 DAY 
order by a.Date desc 
+0

这个作品很有魅力,非常感谢! –

+0

在这里使用NOW()的警告。 NOW()返回当前时间和日期,例如2017-03-24 1330. NOW() - INTERVAL 30 DAY将返回2017-02-22 1330.如果您的订单日期包含Time组件,有意或无意,则任何排除较早时间从该日期起的订单。如果您希望避免NOW()的Time组件,请尝试使用CURDATE()。如果您的订单日期中有Time组件,请尝试使用DATE()。例如WHERE DATE(a.Date)> = CURDATE() - INTERVAL 30天 – toonice

+0

好的!在周末后更新代码以使用'CURDATE()'。 –

1

您可以为此使用日历表或日期维度。

select td.db_date, count(o.OrderId) as Orders 
from time_dimension td 
    left join Orders o 
    on date(o.OrderDate) = db_date 
where td.db_date >= date(adddate(curdate(), interval -30 day)) 
    and td.db_date <= date(curdate()) 
group by td.db_date 

MySQL的日历表参考

+1

非常有趣的阅读!我喜欢当你有日历表时,查询变得可读。不过,我有点不喜欢为此(看似简单)的问题创建一个全新的表格。 –

+0

@DennisHein我很高兴你觉得它很有趣!我了解你对创建表格以便于查询的犹豫。我希望我有一个很好的参考资料,可以用不同尺寸的日期范围对比查询的性能,并比较不同的方法。日历表与堆叠值(接受的答案)。接受的答案非常快,特别是对于30天的窗口,我相信在该范围内的任何差异都不会引人注意。 – SqlZim

0

尝试 -

SELECT dateDuringPeriod, SUM(orderValue), COUNT(orderID) 
FROM 
(
    SELECT dateDuringPeriod, 
      IFNULL(orderID, 0) orderID, 
      IFNULL(orderValue, 0) orderValue 
    FROM 
    (
     SELECT DATE_ADD(CURDATE(), INTERVAL singles + tens DAY) dateDuringPeriod 
     FROM 
     (
      SELECT 0 singles 
      UNION ALL SELECT -1 
      UNION ALL SELECT -2 
      UNION ALL SELECT -3 
      UNION ALL SELECT -4 
      UNION ALL SELECT -5 
      UNION ALL SELECT -6 
      UNION ALL SELECT -7 
      UNION ALL SELECT -8 
      UNION ALL SELECT -9 
     ) singles JOIN 
     (
      SELECT 0 tens 
      UNION ALL SELECT -10 
      UNION ALL SELECT -20 
     ) tens 
    ) datesDuringPeriod LEFT JOIN 
    (
     SELECT orderID, 
       DATE(orderDate) orderDate, 
       orderValue 
     FROM tblOrders 
    ) ordersWithoutTimes 
ON datesDuringPeriod.dateDuringPeriod = ordersWithoutTimes.orderDate 
) tblOrderSummary 
GROUP BY dateDuringPeriod 
ORDER BY dateDuringPeriod; 

我已经创建了一个示例表样本DAT a并且发现这个代码是有效的。

+0

最初的答案更新为MySQL语法(对不起 - 用感冒进行编程,感觉比我想象的更贪婪)。请随时提出您可能遇到的任何问题。 – toonice

+0

嘿,感谢您花时间。可悲的是你的回答并不完全奏效。如果有一天没有订单,相应的行将会丢失。 –

+0

糟糕!我的错。我现在会陷入这个问题。 – toonice