整个数据集的不同计数,按月分组

Posted

技术标签:

【中文标题】整个数据集的不同计数,按月分组【英文标题】:Distinct count for entire dataset, grouped by month 【发布时间】:2018-12-19 20:18:26 【问题描述】:

我正在处理一个大致如下所示的销售订单表 (ORDER)(2018 年 12 月 20 日更新以更接近我的实际数据集):

SOID         SOLINEID         INVOICEDATE         SALESAMOUNT     AC
5            1                2018-11-30          100.00          01
5            2                2018-12-05          50.00           02
4            1                2018-12-12          25.00           17
3            1                2017-12-31          75.00           03
3            2                2018-01-03          25.00           05
2            1                2017-11-25          100.00          17
2            2                2017-11-27          35.00           03
1            1                2017-11-20          15.00           08
1            2                2018-03-15          30.00           17
1            3                2018-04-03          200.00          05

我可以按 SOID 和 SOLINEID 计算平均销售额:

SELECT SUM(SALESAMOUNT) / COUNT(DISTINCT SOID) AS 'Total Sales per Order ($)',
    SUM(SALESAMOUNT) / COUNT(SOLINEID) AS 'Total Sales per Line ($)'
FROM ORDER

这似乎提供了一个非常好的答案,但我得到了一个额外的限制,即这个计数是按年和月计算的。我以为我可以简单地添加

GROUP BY YEAR(INVOICEDATE), MONTH(MONTH)

但这会聚合 SOID,然后执行 COUNT(DISTINCT SOID)。这成为跨越多个月出现的 SOID 的问题,这很常见,因为我们在发货时开具发票。

我想得到这样的东西:

Year     Month     Total Sales Per Order    Total Sales Per Line
2018     11        0.00                     

最痛心的一点是,如果 SOID 跨越多个,我需要某种方式来定义 SOID 将在哪个月份和年份聚合;为此,我会使用 MAX(INVOICEDATE)。

但是,我只是不确定如何解决这个问题。和?子查询?还有什么?我将不胜感激任何帮助,即使它只是指向正确的方向。

【问题讨论】:

【参考方案1】:

您应该为调用和分组选择 Year() 和 month()

SELECT YEAR(INVOICEDATE) year
  , MONTH(INVOICEDATE) month
  , SUM(SALESAMOUNT) / COUNT(DISTINCT SOID) AS 'Total Sales per Order ($)'
  , SUM(SALESAMOUNT) / COUNT(SOLINEID) AS 'Total Sales per Line ($)'
FROM ORDER
GROUP BY YEAR(INVOICEDATE), MONTH(INVOICEDATE)

【讨论】:

此查询将重复计算具有跨越多个月/年的 INVOICEDATE 的 SOID,如在我的示例数据集中。我只希望在最后一个 INVOICEDATE 的月份和年份中计算每个 SOID。【参考方案2】:

这是结果,但数据样本没有 enuf 行来显示月份...

SELECT
    mDateYYYY,
    mDateMM,
    SUM(SALESAMOUNT) / COUNT(DISTINCT t1.SOID) AS 'Total Sales per Order ($)',
    SUM(SALESAMOUNT) / COUNT(SOLINEID) AS 'Total Sales per Line ($)'
FROM DCORDER as t1
left join
    (Select
     SOID
     ,Year(max(INVOICEDATE)) as mDateYYYY
     ,Month(max(INVOICEDATE)) as mDateMM
From DCOrder 
Group By SOID
     ) as t2
 On t1.SOID = t2.SOID

 Group by mDateYYYY, mDateMM

mDateYYYY   mDateMM Total Sales per Order ($)   Total Sales per Line ($)
2018        12      87.50                       58.33

我使用了新的 SQL 仍然是 MAX(INVOICEDATE)(not above),新的 12/20 数据,并排除了 AC=17。

YYYY    MM  Total Sales per Order ($)   Total Sales per Line ($)
2017    11   35.00                       35.00
2018     1  100.00                       50.00
2018     4  215.00                      107.50
2018    12  150.00                       75.00

【讨论】:

当我没有任何限制时,这个查询似乎给了我正确的数字。不幸的是,我简化了我的问题,它确实有两个额外的约束。基本上,我想排除一个会计代码 AC,如果它是 17,我只想看看 2017 和 2018。当我之前尝试添加这个 WHERE 子句时“外部”分组依据,记录总数与未分组查询的总数不对应。当我在子查询中尝试这个时,我的号码仍然关闭。 在 INVOICEDATE 2017/2018 还是在 max(INVOICEDATE) 2017/2018 ?除了这个和AC = 17,以上是否解决了原来的问题?如果是这样,请单击上面的复选标记。此外,我们需要更多的测试数据来证明这一点。方便我们。 我更新了我的示例以更好地反映我的数据。这些订单跨越数月和数年,我在 AC 列中添加了几个 17。 在 INVOICEDATE 2017/2018 或 max(INVOICEDATE) 2017/2018 时仍需要过滤器的答案和数据 ??那么 2016/2017/2018 年我们会砍掉 2016 年的数据但包括其余的数据吗? 2017/2018/2019 怎么样,最大是 2019 年,我们会放弃整个 SOID 吗? (n.b. 额外的数据看起来不错,AC 有 17 改变了结果......更多稍后) 我开始看到这个问题。 SUM(SALESAMOUNT) “应该”按日历年,所以我们将按 INVOICEDATE 分组。当我们计算 SOID 时,我一直要求将这些汇总到 MAX(INVOICEDATE)。我们不能同时拥有两者!假设我想按 INVOICEDATE 保留 SUM(SALESAMOUNT);有没有一种干净的方法来确保我们只计算每个 SOID 一次?

以上是关于整个数据集的不同计数,按月分组的主要内容,如果未能解决你的问题,请参考以下文章

mysql 如何按月分组查询出当前年度每个月的短信数量(数据库中这个月要是为空的话就用0条怎么显示出来)

Pandas 数据透视表和分组按月和小时

sql 按计数获取日期的博客存档格式,并按月/年分组

按月分组的运行计数以汇总销售额

mycat:水平分库之按月分库

分组用户 - 按月累积计数