【问题标题】:Sales and transaction totals by part, grouped by last 24 months按部分划分的销售和交易总额,按过去 24 个月分组
【发布时间】:2015-11-20 01:52:25
【问题描述】:
SELECT det.partNum,
SUM(det.quantity) AS Demand1,
COUNT(det.partNum) AS Call1

FROM details det

JOIN invoice inv ON det.invoice_id = inv.id
WHERE inv.invoice_date
BETWEEN '2015-11-01 00:00:00'
AND '2015-11-31 23:59:59'

GROUP BY partNum

上面的 sql 返回当月的所有零件编号、售出的总数(需求)和零件参与的交易总数(调用)。

我们的供应商想要的是每个零件的这些信息,而且还针对过去 24 个月的每个月进行分组。他们请求的 csv 如下所示(如果只查看过去 3 个月):

Part# | Demand1 | Demand2 | Demand3 | Call1 | Call2 | Call3
123   |       0 |       2 |       0 |     0 |     1 |     0
345   |       6 |       3 |       4 |     1 |     2 |     3

Part# 123: 0 transactions this month (Call1) 0 quantity sold (Demand1)
       1 transaction last month (Call2) 2 quantity sold (Demand2).
       0 transactions two months ago (Call3) 0 quantity sold (Demand3).

Part# 345: 1 transaction this month (Call1) for qty sold of 6 (Demand1)
       2 transactions last month (Call2) for qty sold of 3 (Demand2)
       3 transactions two months ago (Call3) for qty sold of 4 (Demand3)

意识到他们希望将其延长至过去 24 个月。 Demand1/Call1 始终是当前月份。

我使用 WHERE/BETWEEN 语句来显示日期的来源,并演示如何获得当月部件的准确报告。

我不知道该怎么做就是满足 24 个月的需求和需求。这是供应商希望数据采用的格式。这不是我的选择。任何帮助使其按预期工作将不胜感激。

谢谢

编辑

我删除了 sql-server 标记。对于那个很抱歉。这只是 MySQL。

另外,我正在从下面添加我的回复...

查看 DATEDIFF、TIMESTAMPDIFF 甚至 PERIOD_DIFF。但实际上似乎没有人返回我需要的东西。需要发生的是第一个需求列应该搜索当前月份的第 1 天(包括)到下个月的第 1 天(不包括)。下一个需求列应搜索当前月份 - 一个月第 1 天(含)到下个月 - 一个月第 1 天(不含)。并且每个后续列都应该搜索相同的参数,每列减去一个额外的月份。我不认为仅仅使用 DATEDIFF 就可以精确地完成。

我希望这是有道理的。

再次感谢您的帮助。

【问题讨论】:

  • 你能简单地按年+月分组吗?
  • 我建议按零件编号、年份和月份进行分组,然后以供应商要求的形式获取数据。
  • 我需要按零件编号收集的所有信息。每个部件号将有 48 列。我不知道如何通过按年+月分组来实现这一点。
  • 垫子,我会搜索枢轴,但是当我这样做的时候,你能提供一些例子吗?

标签: mysql


【解决方案1】:

如果我正确理解了您的问题,您可以这样做:

SELECT 
  det.partNum,
  SUM(case when inv.invoice_date >= dateadd(month, -3, @currMonth) and inv.invoice_date < dateadd(month, -2, @currMonth) then det.quantity else 0) AS Demand1,
  SUM(case when inv.invoice_date >= dateadd(month, -2, @currMonth) and inv.invoice_date < dateadd(month, -1, @currMonth) then det.quantity else 0) AS Demand2,
...
FROM details det

JOIN invoice inv ON det.invoice_id = inv.id
WHERE 
  inv.invoice_date >= '2015-11-01 00:00:00' AND inv.invoice_date < '2015-12-01'

GROUP BY partNum

这使用具有当前月份开始日期的变量来使 SQL 更简单。我还更改了 where 子句,你真的应该使用 >= +

【讨论】:

  • 感谢您的快速回复。由于我们没有过滤掉当月的记录,因此是否需要 WHERE 子句?我只是将它放在原始示例中以显示当前月份的可接受范围。
  • 我在第 3 行遇到语法错误。此外,这没有为调用提供任何列。我不仅需要汇总销售额,还需要计算销售额的次数。
【解决方案2】:

这可能会让您开始使用透视查询。

;WITH cte AS 
(
    SELECT  det.partNum,
            SUM(det.quantity) AS DemandSum,
            COUNT(det.partNum) AS CallCount,
            DATEDIFF(MONTH,inv.invoice_date, GETDATE()) + 1 MonthDiff
    FROM    details det
            JOIN invoice inv ON det.invoice_id = inv.id
    GROUP BY det.partNum, DATEDIFF(MONTH,inv.invoice_date, GETDATE()) + 1

)
SELECT t.partNum,
       [Demand1],[Demand2],[Demand3],[Demand4],[Demand5],[Demand6],[Demand7],[Demand8],[Demand9],[Demand10],[Demand11],[Demand12],
       [Demand13],[Demand14],[Demand15],[Demand16],[Demand17],[Demand18],[Demand19],[Demand20],[Demand21],[Demand22],[Demand23],[Demand24],
       [Call1],[Call2],[Call3],[Call4],[Call5],[Call6],[Call7],[Call8],[Call9],[Call10],[Call11],[Call12],
       [Call13],[Call14],[Call15],[Call16],[Call17],[Call18],[Call19],[Call20],[Call21],[Call22],[Call23],[Call24]
FROM (SELECT DISTINCT partNum FROM cte) t
LEFT JOIN (
        SELECT * FROM (
            SELECT partNum, DemandSum, CONCAT('Demand',MonthDiff) ColName FROM cte
        ) c PIVOT (SUM(DemandSum) FOR ColName IN ([Demand1],[Demand2],[Demand3],[Demand4],[Demand5],[Demand6],[Demand7],[Demand8],[Demand9],[Demand10],[Demand11],[Demand12],
                                                [Demand13],[Demand14],[Demand15],[Demand16],[Demand17],[Demand18],[Demand19],[Demand20],[Demand21],[Demand22],[Demand23],[Demand24])    
        ) p
    ) ds ON ds.partNum = t.partNum
LEFT JOIN (
        SELECT * FROM (
            SELECT partNum, CallCount, CONCAT('Call',MonthDiff) ColName FROM cte
        ) c PIVOT (COUNT(CallCount) FOR ColName IN ([Call1],[Call2],[Call3],[Call4],[Call5],[Call6],[Call7],[Call8],[Call9],[Call10],[Call11],[Call12],
                                                [Call13],[Call14],[Call15],[Call16],[Call17],[Call18],[Call19],[Call20],[Call21],[Call22],[Call23],[Call24])    
        ) p
    ) cc ON cc.partNum = t.partNum

如果这太令人困惑,您可以使用 CASE 方法。不过,我会做的与其他答案有所不同..

SELECT 
    det.partNum,
    SUM(case WHEN DATEDIFF(MONTH, inv.invoice_date, GETDATE()) = 0 then det.quantity else 0 end) AS Demand1,
    SUM(case WHEN DATEDIFF(MONTH, inv.invoice_date, GETDATE()) = 1 then det.quantity else 0 end) AS Demand2,
    SUM(case WHEN DATEDIFF(MONTH, inv.invoice_date, GETDATE()) = 2 then det.quantity else 0 end) AS Demand3,
    COUNT(case WHEN DATEDIFF(MONTH, inv.invoice_date, GETDATE()) = 0 then det.partNum end) AS Call1,
    COUNT(case WHEN DATEDIFF(MONTH, inv.invoice_date, GETDATE()) = 1 then det.partNum end) AS Call2,
    COUNT(case WHEN DATEDIFF(MONTH, inv.invoice_date, GETDATE()) = 2 then det.partNum end) AS Call3
FROM 
    details det
    JOIN invoice inv ON det.invoice_id = inv.id
GROUP BY 
    det.partNum

您可以在这里获得所有 24 个月的完整脚本。SQL Fiddle

【讨论】:

  • 感谢您的帮助,但我得到 #1582 - 运行语句时调用本机函数 'DATEDIFF' 时的参数计数不正确。
  • 你有 mysql 和 sql-server 标记.. 我假设你只使用 mysql 的错误
  • 我能够在没有 MONTH 参数并将 GETDATE 更改为 CURDATE 的情况下运行该语句。但它不会在 Demand/Call 列中返回每月总计。
  • JamieD77,很抱歉。是的,只有 MySQL。
  • 查看 DATEDIFF、TIMESTAMPDIFF 甚至 PERIOD_DIFF。但实际上似乎没有人返回我需要的东西。需要发生的是第一个需求列应该搜索当前月份的第 1 天(包括)到下个月的第 1 天(不包括)。下一个需求列应搜索当前月份 - 一个月第 1 天(含)到下个月 - 一个月第 1 天(不含)。并且每个后续列都应该搜索相同的参数,每列减去一个额外的月份。我不认为仅仅使用 DATEDIFF 就可以精确地完成。
猜你喜欢
  • 2020-02-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-04
  • 1970-01-01
相关资源
最近更新 更多