【问题标题】:Join against date range, aggregate by SUM根据日期范围加入,按 SUM 聚合
【发布时间】:2012-07-09 12:26:07
【问题描述】:

我需要收集某个类别商品的销售额总和,按选定日期范围(可能从一周到 12 周)按天分组,并在未发生交易的天返回 0 而不是 NULL。

我最初的想法是使用一个名为“日历”的预填充表(如下所示),该表有大约 10 年的日期,我可以将其加入我的“产品”表,以获得没有销售发生的天数为 0 SUM .

结果太大而无法处理,因此我尝试首先将选定的日期范围复制到一个名为“datetable”的空表中,该表与“日历”具有相同的列名。所以我有 3 张桌子:

日历”表。它有 10 年的日期,并带有以下列名称:

IsoDate       DayNameOfWeek

2012-01-01       Sun
2012-01-02       Mon
2012-01-03       Tue
2012-01-04       Wed
2012-01-05       Thu
2012-01-06       Fri
2012-01-07       Sat
2012-01-08       Sun
2012-01-09       Mon
2012-01-10       Tue
etc for 10yrs

datetable”表(这是创建为空的,有两列从“日历”表中预填充,因此 LEFT JOIN 的日期范围数据更紧​​凑):

IsoDate        DayNameOfWeek

产品”表。这是我存储每个 ProductCat 销售额的地方:

ExpDate     ProductCat  Amount

2012-01-03    28          232
2012-01-04    29          100
2012-01-04    29          1002
2012-01-06    12          12
2012-01-06    29          9
2012-01-07    10          100
2012-01-07    29          122
2012-01-07    29          17

我正在寻找基于单个“ProductCat”编号的输出,在本例中为 29:

IsoDate     DayNameOfWeek   AmountSummed

2012-01-01     Sun      0
2012-01-02     Mon      0
2012-01-03     Tue      0
2012-01-04     Wed      1102
2012-01-05     Thu      0
2012-01-06     Fri      9
2012-01-07     Sat      139
2012-01-08     Sun      0
2012-01-09     Mon      0
2012-01-10     Tue      0

我的代码如下。初始插入工作正常,但我不确定使第二部分与 JOIN 和 SUM 一起工作的语法:

INSERT INTO datetable (IsoDate, DayNameOfWeek)
SELECT IsoDate, DayNameOfWeek
FROM calendar
WHERE IsoDate 
BETWEEN '2012-07-01' AND '2012-07-10'

SELECT ExpDate, SUM(IFNULL(Amount, 0))
AS AmountSummed
FROM products
WHERE ProductCat = 29
AND ExpDate BETWEEN '2012-07-01' AND '2012-07-10'
LEFT JOIN products 
ON datetable.IsoDate=products.ExpDate
    GROUP BY datetable.IsoDate

编辑

这是现在可以使用的代码:

SELECT C.IsoDate,IFNULL(SUM(P.Amount),0) AS AmountSummed
FROM calendar C LEFT OUTER JOIN products P ON C.IsoDate=P.ExpDate
AND P.ProductCat = 29
WHERE C.IsoDate BETWEEN '2012-07-01' AND '2012-07-10'
GROUP BY C.IsoDate, C.DayNameOfWeek
ORDER BY C.IsoDate

【问题讨论】:

    标签: sql sqlite group-by


    【解决方案1】:

    你几乎得到了你需要的东西。但是,您不需要 datetable

    您的查询应如下所示:

    SELECT C.IsoDate, C.DayNameOfWeek, IFNULL(SUM(P.Amount),0) AS AmountSummed
    FROM calendar C LEFT JOIN products P ON C.IsoDate=P.ExpDate
    WHERE C.IsoDate BETWEEN '2012-07-01' AND '2012-07-10'
      AND P.ProductCat = 29
    GROUP BY C.IsoDate, C.DayNameOfWeek
    ORDER BY C.IsoDate
    

    如果您真的想使用您的datetable,只需将其替换为calendar 并删除C.IsoDate BETWEEN '2012-07-01' AND '2012-07-10'(假设您开始之前datetable 为空)因为datetime 已经包含所有日期你正在寻找。

    【讨论】:

    • 嗨 Holger,这很好用,因为它让我不再需要日期表......但我似乎无法在 10 天范围内返回 0 总和“产品”表中没有条目。所以天数:01、02、05、08、09、10。我可以做一些调整来获得它吗?谢谢M
    • @MarcoPolo,我切换了 IFNULL 和 SUM 的顺序。那应该解决它。或者,您可以只使用 TOTAL() 而不是 IFNULL 和 SUM,但它会返回一个浮点数 (0.0)。
    • 嗨 Holger,我稍微修改了你的代码,因为我仍然无法让它工作,它仍然在没有条目的情况下被砍掉几天。所以我将“P.ProductCat = 29”向上移动到 JOIN 位,并将日期范围留在 WHERE 中,它似乎可以工作。 :) 感谢您指出我正确的方向。米
    猜你喜欢
    • 2018-01-09
    • 1970-01-01
    • 2020-07-01
    • 1970-01-01
    • 2018-09-02
    • 1970-01-01
    • 1970-01-01
    • 2016-12-27
    • 1970-01-01
    相关资源
    最近更新 更多