【问题标题】:Building report with date gaps建立具有日期间隔的报告
【发布时间】:2019-02-13 11:02:15
【问题描述】:

我需要根据卖家在特定日期范围内的销售情况进行报告。 我遇到的问题是报告还应该包含当天没有销售的卖家。

供应商(表格)

id | name
----------
 1 | John
 2 | Tom

销售额(表)

id | vendor_id |    date        | status | price
------------------------------------------------
 1 |        1  |    2019-01-01  |    0   | 100
 2 |        1  |    2019-01-01  |    0   | 100 
 3 |        2  |    2019-01-01  |    0   | 100
 4 |        2  |    2019-01-02  |    0   | 100 

所需报告:2019-01-012019-01-04

之间的总销售额
date        |vendor| total
--------------------------
2019-01-01  | John | 200
2019-01-01  | Tom  | 100
2019-01-02  | John | 0
2019-01-02  | Tom  | 100
2019-01-03  | John | 0
2019-01-03  | Tom  | 0
2019-01-04  | John | 0
2019-01-04  | Tom  | 0

为了生成日期序列,我使用日期生成器here

当我交叉(左连接)使用sales 生成的日期时,我得到以下信息:

SELECT date_generator.daily_date, vendors.name, sales.price
        FROM ( 
            SELECT DATE_ADD(@startDate, INTERVAL (@i:=@i + 1) - 1 DAY) AS daily_date   
            FROM information_schema.columns, (SELECT @i:=0) gen_sub   
            WHERE DATE_ADD(@startDate, INTERVAL @i DAY) BETWEEN @startDate AND @endDate 
        ) date_generator 
        LEFT JOIN sales ON DATE(sales.date) = DATE(date_generator.daily_date)
        LEFT JOIN vendors ON vendors.id = sales.vendor_id
ORDER BY date_generator.daily_date

date        |vendor| price
--------------------------
2019-01-01  | John | 100
2019-01-01  | John | 100
2019-01-01  | Tom  | 100
2019-01-02  | Tom  | 100
2019-01-03  | null | null
2019-01-04  | null | null

你能给我一些技巧来获得供应商和日期的分组吗?

【问题讨论】:

  • 您的方法似乎错误。首先,您从不汇总和 sum() 那么您如何期望“200”?其次,虽然带有子查询的日期生成器很智能,但它不能满足您的需求,因为每个日期(天)您只能获得与许多供应商在该日期有销售一样多的行,并且使用左连接您会得到NULL 表示没有供应商有销售的日期。我建议你简化查询(除了添加分组和聚合)像这样db-fiddle.com/f/2TQJKn2SqZwEEqxcoqqc9M/1 并将日期间隔逻辑传输到应用程序层。

标签: mysql sql


【解决方案1】:

由于有些日子没有销售,您将有一个 NULL sales.vendor.id 值,所以 JOINvendors 没有任何意义。为确保您在所有日期获得所有供应商,您需要从date_generatorvendors 执行CROSS JOIN,然后将LEFT JOIN 转换为销售。然后你需要把SUMsales.priceGROUP BY 的日期和供应商取到你想要的输出:

SELECT date_generator.daily_date, vendors.name, SUM(sales.price)
        FROM ( 
            SELECT DATE_ADD(@startDate, INTERVAL (@i:=@i + 1) - 1 DAY) AS daily_date   
            FROM information_schema.columns, (SELECT @i:=0) gen_sub   
            WHERE DATE_ADD(@startDate, INTERVAL @i DAY) BETWEEN @startDate AND @endDate 
        ) date_generator 
        CROSS JOIN vendors
        LEFT JOIN sales ON DATE(sales.date) = DATE(date_generator.daily_date) AND vendors.id = sales.vendor_id
GROUP BY date_generator.daily_date, vendors.name

【讨论】:

  • 非常好的答案,我吓坏了。谢谢你尼克!
  • @Miguel 不用担心。很高兴我能帮上忙。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-13
  • 1970-01-01
  • 1970-01-01
  • 2021-07-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多