MySQL:显示每月销售额,包括未进行销售的月份

时间:2011-08-31 01:26:37

标签: mysql date summary sales

我需要真正的专业DBA帮助!我找不到使用LEFT JOIN,UNION,UNION ALL或者IFNULL(salesblah,0)在销售数据表日期表上的合理解决方案。由于销售代表可能存在差距,因此单独对销售数据运行查询。当然,我可以在PHP中创建一个数组来按日期汇总数据,但是必须要有一个我看不到的优雅解决方案,而这个个人挑战让我疲惫不堪。必须有一个简短而甜蜜的解决方案。

在服务器上使用MySQL 5.5.15,销售数据的摘录(目前为800,000行,每天增长)如下所示:

    Rep         Date         QtyOrdered     PriceEach
    --------------------------------------------------
    1         2011-06-05              4        1457.23
    1         2011-08-01              1        3342.54
    1         2011-08-11             12         112.23
    2         2011-05-02              3        2654.23
    2         2011-08-23             22         423.43
    .            ...                ...            ...

另一张表只是2000-01-01至2034-12-31之间的一列日期

使用(或不使用)日期表,当我在查询中调用rep 1时,如何获得此结果:

YYYY-MM      Total Sales
------------------------
2010-08               0
2010-09               0
2010-10               0
2010-11               0
2010-12               0
2011-01               0
2011-02               0
2011-03               0
2011-04               0
2011-05               0
2011-06         5828.92
2011-07               0
2011-08         4960.14

我真的希望收掉那些不礼貌的言辞。谢谢你的才华。

编辑:Derek的左连接解决方​​案省略了非零月份。 Nerf的子查询方法总计为一个月。我相信正是GROUP BY正在杀死非零月份。

谢谢!我相信最简单的方法是让PHP通过数组运行结果。最终,这是通过GD构建一个月的图表,混合解决方案可以在该部分中省去一步。

再次感谢你!

3 个答案:

答案 0 :(得分:1)

这应该让你非常接近。没有经过测试,但逻辑应该是正确的。

select 
   cast(year(dt.date) as varchar(4)) + '-' + cast(month(dt.date) as varchar(2)),
   sum(QtyOrdered * PriceEach)
from salesdata sd
right join datetbl dt
  on sd.date = dt.date
where sd.rep = 1 and dt.date between '8/1/2010' and '8/31/2011'
group by cast(year(dt.date) as varchar(4)) + '-' + cast(month(dt.date) as varchar(2))

答案 1 :(得分:1)

SELECT CONCAT_WS("-",  YEAR(date), DATE_FORMAT(date, '%m') ) AS "YYYY-MM", SUM(Total_Sales) AS "Total Sales"
FROM(
     SELECT dt.date, SUM(QtyOrdered * PriceEach) AS Total_Sales
    FROM sales_data sd
         LEFT JOIN datetbl dt
         ON sd.Date = dt.date
    WHERE sd.rep = 1 AND dt.date BETWEEN '2011-08-01' AND '2011-08-31'
        GROUP BY dt.date
         )  AS derived_table

答案 2 :(得分:1)

我遇到了同样的问题,我得到的解决方案没有使用JOIN或任何复杂的东西。要避免的是按总计分组。这将显示按年,月和日排序的所有销售,包括根本没有销售的日期(dayTotal将等于0)

SELECT Year(transactions.paymentdate) AS orderYear,Month(transactions.paymentdate) AS orderMonth, Day(transactions.paymentdate) AS orderDay,
    SUM(transactions.amount) AS dayTotal
    FROM transactions
    group by orderYear desc,orderMonth desc, orderDay desc