B1查询|不同时间段即 1 / 3 / 6 / 12 个月的月销售额合并

问题描述

真的很纠结这个。寻找一种查询不同时间跨度的销售量的方法,所有这些都放在一个表中。

假设现在是 8 月 13 日。然后我想总结以下销售量:

  • 7 月 1 日 00:00:00 - 7 月 31 日 11:59:59(过去 1 个月)
  • 5 月 - 1 日 00:00:00 - 7 月 31 日 11:59:59(过去 3 个月)
  • 2 月 1 日 00:00:00 - 7 月 31 日 11:59:59(过去 6 个月)
  • 8 月 1 日 00:00:00 - 7 月 31 日 11:59:59(过去 12 个月)

我尝试重用数据透视查询示例中的片段,这些片段可以找到与销售量相关但没有成功。 我从头开始,首先尝试创建可用于时间跨度的日期时间,但这已经非常繁琐,而且不知何故感觉不对。

我认为我需要以 4 个单独的查询结束,然后需要将这些查询连接起来以将所有列合并到一个表中:

物品名称 项目代码 Sal.vol 1 月 Sal.vol 3 个月 Sal.vol 6 个月 Sal.vol 12 个月
项目 1 10102251 10 30 60 120
项目 2 10120101 14 35 78 181

我目前的进展:

SELECT
  T1.itemcode,month(T1.[docDate]) as month,T3.ItemName,SUM(t1.quantity )
FROM INV1 T1 INNER JOIN OINV T2 ON T1.docentry = T2.docentry INNER JOIN OITM T3 ON T1.ItemCode = T3.ItemCode
WHERE T1.[docDate] between DATEADD(month,-4,GETDATE()) and DATEADD(month,-1,GETDATE()) AND T1.ItemCode LIKE '1%' AND T3.ItmsGrpCod = 100
Group By  T1.itemcode,month(T1.[docDate])

对于我的约会时间,我想按如下方式构建它们:

DECLARE @date date = month(DATEADD(month,GETDATE())) + '-01-' + year(DATEADD(month,GETDATE()));
DECLARE @datetime datetime = @date;     
SELECT @datetime AS '@datetime'

但是我还没有成功,因为我在 int 到日期转换方面遇到了麻烦,我认为 Jan-Sep 的月份()将不起作用,因为它只返回 1 位数字...

有人能帮我指出正确的方向吗?

提前致谢!


更新 1:

@imerd 为我指明了正确的方向。我能够根据需要构建我的查询分享我的中间结果,因为这现在有效。 Query 需要一些清理和优化,重复出现的主要部分外包到第二个函数中。

create function MonthFirst (@period integer ) returns date
as begin
declare @returnperiod date 
set @returnperiod = cast(cast(year(DATEADD(month,@period,GETDATE())) as varchar(4)) + '-' +
    cast(month(DATEADD(month,GETDATE())) as varchar(2)) + '-01' as date)
 return @returnperiod
end
-- drop function dbo.MonthFirst

SELECT S12.ItemCode,o1.ItemName,S12.[last 12 months],S6.[last 6 months],S3.[last 3 months],S1.[last month] FROM 
(SELECT
   T1.itemcode,CAST(SUM(t1.quantity) AS int) AS 'last 12 months'
FROM DLN1 T1 INNER JOIN ODLN T2 ON T1.docentry = T2.docentry INNER JOIN OITM T3 ON T1.ItemCode = T3.ItemCode
WHERE T1.[docDate] between CAST(dbo.MonthFirst(-12) AS datetime) AND  DATEADD(second,CAST(dbo.MonthFirst(0) AS datetime)) 
      AND T3.validFor = 'Y' AND T3.ItmsGrpCod = 100 --products / 102 raw materials
      AND T2.CANCELED = 'N'
Group By T1.itemcode) S12

FULL JOIN 

(SELECT
   T1.itemcode,CAST(SUM(t1.quantity) AS int) AS 'last 6 months'
FROM DLN1 T1 INNER JOIN ODLN T2 ON T1.docentry = T2.docentry INNER JOIN OITM T3 ON T1.ItemCode = T3.ItemCode
WHERE T1.[docDate] between CAST(dbo.MonthFirst(-6) AS datetime) AND  DATEADD(second,CAST(dbo.MonthFirst(0) AS datetime)) 
      AND T3.validFor = 'Y' AND T3.ItmsGrpCod = 100 --products / 102 raw materials
      AND T2.CANCELED = 'N'
Group By T1.itemcode) S6 on S12.ItemCode = S6.ItemCode

FULL JOIN 

(SELECT
   T1.itemcode,CAST(SUM(t1.quantity) AS int) AS 'last 3 months'
FROM DLN1 T1 INNER JOIN ODLN T2 ON T1.docentry = T2.docentry INNER JOIN OITM T3 ON T1.ItemCode = T3.ItemCode
WHERE T1.[docDate] between CAST(dbo.MonthFirst(-3) AS datetime) AND  DATEADD(second,CAST(dbo.MonthFirst(0) AS datetime)) 
      AND T3.validFor = 'Y' AND T3.ItmsGrpCod = 100 --products / 102 raw materials
      AND T2.CANCELED = 'N'
Group By T1.itemcode) S3 on S12.ItemCode = S3.ItemCode

FULL JOIN 

(SELECT
   T1.itemcode,CAST(SUM(t1.quantity) AS int) AS 'last month'
FROM DLN1 T1 INNER JOIN ODLN T2 ON T1.docentry = T2.docentry INNER JOIN OITM T3 ON T1.ItemCode = T3.ItemCode
WHERE T1.[docDate] between CAST(dbo.MonthFirst(-1) AS datetime) AND  DATEADD(second,CAST(dbo.MonthFirst(0) AS datetime)) 
      AND T3.validFor = 'Y' AND T3.ItmsGrpCod = 100 --products / 102 raw materials
      AND T2.CANCELED = 'N'
Group By T1.itemcode) S1 on S12.ItemCode = S1.ItemCode

INNER JOIN OITM o1 on S12.ItemCode = o1.ItemCode

ORDER BY o1.ItemName

更新 2:

我现在结合了来自@imerd 和@Gordon Linoff 的建议/提示,得到了这个漂亮的小查询,这几乎正是我想要的。

非常感谢!

这是我的解决方案:

DECLARE @period integer = -12
DECLARE @startperiod date
DECLARE @endperiod date 
SET @startperiod = CAST(cast(year(DATEADD(month,GETDATE())) AS varchar(4)) + '-' +
    cast(month(DATEADD(month,GETDATE())) AS varchar(2)) + '-01' AS date)
SET @endperiod = CAST(cast(year(DATEADD(month,GETDATE())) AS varchar(2)) + '-01' AS datetime)

SELECT T1.ItemCode,sum(case when datediff(month,T1.[docDate],GETDATE()) <= 12 then t1.quantity else 0 end) as month_12,GETDATE()) <= 6 then t1.quantity else 0 end) as month_6,GETDATE()) <= 3 then t1.quantity else 0 end) as month_3,GETDATE()) = 1 then t1.quantity else 0 end) as month_1
FROM DLN1 T1 INNER JOIN ODLN T2 ON T1.docentry = T2.docentry INNER JOIN OITM T3 ON T1.ItemCode = T3.ItemCode
WHERE T1.[docDate] between CAST(@startperiod AS datetime) AND  DATEADD(second,CAST(@endperiod AS datetime)) 
      AND T3.validFor = 'Y' AND T3.ItmsGrpCod = 100 --products / 102 raw materials
      AND T2.CANCELED = 'N'
GROUP BY T1.ItemCode,T3.ItemName
ORDER BY T3.ItemName ASC

@Gordon Linoff: '=' 需要是 '

再次感谢您的快速帮助!

解决方法

这看起来像一个简单的条件聚合示例:

select itemname,itemcode
       sum(case when datediff(month,date,1) = 1 then quantity else 0 end) as month_1,sum(case when datediff(month,1) <= 3 then quantity else 0 end) as month_3,1) <= 6 then quantity else 0 end) as month_6,1) <= 12 then quantity else 0 end) as month_12
from t
group by itemname,itemcode;

您的查询比您的描述所暗示的要复杂,但这应该会告诉您如何进行问题核心的计算。

请注意,datediff() 计算两个日期之间边界的数量,因此非常适用于日历月。

,

转换需要调整将所有输入转换为单一数据类型,然后转换为日期数据类型 -

对于美式日期格式

declare @date date = cast( cast(month(DATEADD(month,@period,GETDATE())) as varchar(2)) + '-01-' 
        + cast(year(DATEADD(month,GETDATE())) as varchar(4)) as date)

对于 ISO 日期格式

declare @date date = cast(cast(year(DATEADD(month,-1,GETDATE())) as varchar(4)) + '-' +
    cast(month(DATEADD(month,GETDATE())) as varchar(2))
    + '-01' as date)

假设 ISO 格式是我的小脑子,我从来不明白为什么 Mon DD YYYY 对演示以外的数据处理很实用

创建一个可以传递“要报告的月份数”的函数 - 以减少主报告查询中的代码

create function MonthFirst (@period integer ) returns date
as begin
declare @returnperiod date 
set @returnperiod = cast(cast(year(DATEADD(month,GETDATE())) as varchar(2))
    + '-01' as date)
 return @returnperiod
end

然后根据需要在查询中使用函数(例如)

select [3 Months Ago] = dbo.MonthFirst(-2)  -- 2020-12-01
select [Last Month] = dbo.MonthFirst(-1)  -- 2021-02-01
select [This Month] = dbo.MonthFirst(0)  -- 2021-03-01
select [Next Month] = dbo.MonthFirst(1)  -- 2021-04-01