B1查询 |不同时间段(即 1 / 3 / 6 / 12 个月)的月度销售额合并
B1 query | Monthly sales consolidated for different time periods (i.e. 1 / 3 / 6 / 12 months)
真的很挣扎这个。寻找一种查询不同时间跨度的销售量的方法,所有这些都放在一个 table.
假设现在是 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 个单一查询结束,然后需要将这些查询连接起来以将所有列合并为一个 table:
ItemName
ItemCode
Sal.vol 1 mth
Sal.vol 3 mths
Sal.vol 6 mths
Sal.vol 12 mths
Item 1
10102251
10
30
60
120
Item 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, T3.ItemName, month(T1.[docDate])
对于我的约会时间,我想按如下方式构建它们:
DECLARE @date date = month(DATEADD(month, -1, GETDATE())) + '-01-' + year(DATEADD(month, -1, GETDATE()));
DECLARE @datetime datetime = @date;
SELECT @datetime AS '@datetime'
我还没有成功,因为我在转换 int 到日期时遇到问题,我认为 1 月至 9 月的 month() 将不起作用,因为它 return 只有 1 位数字...
谁能帮我指明正确的方向?
提前致谢!
更新 1:
@imerd 为我指出了正确的方向。我能够根据需要构建查询。分享我的中间结果,因为这目前有效。查询需要一些清理和优化,并将重复出现的主要部分外包到第二个函数中。
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, @period, 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, -1, 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, -1, 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, -1, 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, -1, 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 的 suggestions/hints 并得到了这个漂亮的小查询,它几乎正是我想要的。
非常感谢!
这是我的解决方案:
DECLARE @period integer = -12
DECLARE @startperiod date
DECLARE @endperiod date
SET @startperiod = CAST(cast(year(DATEADD(month, @period, GETDATE())) AS varchar(4)) + '-' +
cast(month(DATEADD(month, @period, GETDATE())) AS varchar(2)) + '-01' AS date)
SET @endperiod = CAST(cast(year(DATEADD(month, 0, GETDATE())) AS varchar(4)) + '-' +
cast(month(DATEADD(month, 0, GETDATE())) AS varchar(2)) + '-01' AS datetime)
SELECT T1.ItemCode, T3.ItemName,
sum(case when datediff(month, T1.[docDate], GETDATE()) <= 12 then t1.quantity else 0 end) as month_12,
sum(case when datediff(month, T1.[docDate], GETDATE()) <= 6 then t1.quantity else 0 end) as month_6,
sum(case when datediff(month, T1.[docDate], GETDATE()) <= 3 then t1.quantity else 0 end) as month_3,
sum(case when datediff(month, T1.[docDate], 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, -1, 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:“=”需要为“<=”,因为我希望销售量来自过去 12 个月的所有数量,而不是一年前一个月的数量。
再次感谢您的快速帮助!
转换需要调整将所有输入转换为单一数据类型,然后转换为日期数据类型 -
美式日期格式
declare @date date = cast( cast(month(DATEADD(month, @period, GETDATE())) as varchar(2)) + '-01-'
+ cast(year(DATEADD(month, @period, GETDATE())) as varchar(4)) as date)
对于 ISO 日期格式
declare @date date = cast(cast(year(DATEADD(month, -1, GETDATE())) as varchar(4)) + '-' +
cast(month(DATEADD(month, -1, 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, @period, GETDATE())) as varchar(4)) + '-' +
cast(month(DATEADD(month, @period, 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
这看起来像是一个简单的条件聚合示例:
select itemname, itemcode
sum(case when datediff(month, date, 1) = 1 then quantity else 0 end) as month_1,
sum(case when datediff(month, date, 1) <= 3 then quantity else 0 end) as month_3,
sum(case when datediff(month, date, 1) <= 6 then quantity else 0 end) as month_6,
sum(case when datediff(month, date, 1) <= 12 then quantity else 0 end) as month_12
from t
group by itemname, itemcode;
您的查询比您的描述所暗示的要复杂,但这应该会告诉您如何进行问题核心的计算。
请注意,datediff()
计算两个日期之间 边界 的数量,因此非常适合日历月。
真的很挣扎这个。寻找一种查询不同时间跨度的销售量的方法,所有这些都放在一个 table.
假设现在是 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 个单一查询结束,然后需要将这些查询连接起来以将所有列合并为一个 table:
ItemName | ItemCode | Sal.vol 1 mth | Sal.vol 3 mths | Sal.vol 6 mths | Sal.vol 12 mths |
---|---|---|---|---|---|
Item 1 | 10102251 | 10 | 30 | 60 | 120 |
Item 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, T3.ItemName, month(T1.[docDate])
对于我的约会时间,我想按如下方式构建它们:
DECLARE @date date = month(DATEADD(month, -1, GETDATE())) + '-01-' + year(DATEADD(month, -1, GETDATE()));
DECLARE @datetime datetime = @date;
SELECT @datetime AS '@datetime'
我还没有成功,因为我在转换 int 到日期时遇到问题,我认为 1 月至 9 月的 month() 将不起作用,因为它 return 只有 1 位数字...
谁能帮我指明正确的方向?
提前致谢!
更新 1:
@imerd 为我指出了正确的方向。我能够根据需要构建查询。分享我的中间结果,因为这目前有效。查询需要一些清理和优化,并将重复出现的主要部分外包到第二个函数中。
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, @period, 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, -1, 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, -1, 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, -1, 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, -1, 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 的 suggestions/hints 并得到了这个漂亮的小查询,它几乎正是我想要的。
非常感谢!
这是我的解决方案:
DECLARE @period integer = -12
DECLARE @startperiod date
DECLARE @endperiod date
SET @startperiod = CAST(cast(year(DATEADD(month, @period, GETDATE())) AS varchar(4)) + '-' +
cast(month(DATEADD(month, @period, GETDATE())) AS varchar(2)) + '-01' AS date)
SET @endperiod = CAST(cast(year(DATEADD(month, 0, GETDATE())) AS varchar(4)) + '-' +
cast(month(DATEADD(month, 0, GETDATE())) AS varchar(2)) + '-01' AS datetime)
SELECT T1.ItemCode, T3.ItemName,
sum(case when datediff(month, T1.[docDate], GETDATE()) <= 12 then t1.quantity else 0 end) as month_12,
sum(case when datediff(month, T1.[docDate], GETDATE()) <= 6 then t1.quantity else 0 end) as month_6,
sum(case when datediff(month, T1.[docDate], GETDATE()) <= 3 then t1.quantity else 0 end) as month_3,
sum(case when datediff(month, T1.[docDate], 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, -1, 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:“=”需要为“<=”,因为我希望销售量来自过去 12 个月的所有数量,而不是一年前一个月的数量。
再次感谢您的快速帮助!
转换需要调整将所有输入转换为单一数据类型,然后转换为日期数据类型 -
美式日期格式
declare @date date = cast( cast(month(DATEADD(month, @period, GETDATE())) as varchar(2)) + '-01-'
+ cast(year(DATEADD(month, @period, GETDATE())) as varchar(4)) as date)
对于 ISO 日期格式
declare @date date = cast(cast(year(DATEADD(month, -1, GETDATE())) as varchar(4)) + '-' +
cast(month(DATEADD(month, -1, 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, @period, GETDATE())) as varchar(4)) + '-' +
cast(month(DATEADD(month, @period, 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
这看起来像是一个简单的条件聚合示例:
select itemname, itemcode
sum(case when datediff(month, date, 1) = 1 then quantity else 0 end) as month_1,
sum(case when datediff(month, date, 1) <= 3 then quantity else 0 end) as month_3,
sum(case when datediff(month, date, 1) <= 6 then quantity else 0 end) as month_6,
sum(case when datediff(month, date, 1) <= 12 then quantity else 0 end) as month_12
from t
group by itemname, itemcode;
您的查询比您的描述所暗示的要复杂,但这应该会告诉您如何进行问题核心的计算。
请注意,datediff()
计算两个日期之间 边界 的数量,因此非常适合日历月。