在每年的开始日期获得有效的订单

时间:2018-07-13 08:50:41

标签: sql sql-server tsql

在包含 Order 信息的表(称为 Order )中,我们具有以下字段:

  1. OrderId int
  2. OrderDate 日期
  3. BindingTime int

绑定时间以月为单位。

订单在其OrderDateDATEADD(mm, BindingTime, OrderDate)之间被称为“有效”。

我想做的是按年份对订单进行分组,这样,如果订单在一年的第一天处于“活动状态”,则将其考虑在内。目的是计算每年的入站和出站订单。因此,查询结果将是COUNT的订单和年份。而按年份,则是指该年第一天有效的订单数。

请记住,我们希望在结果中包含两个给定数字之间的所有年份。例如。如果2016年第一天没有活动订单,我们仍然希望在(0,2016)中有一行。

2 个答案:

答案 0 :(得分:1)

我使用了递归CTE来生成年份范围,因此不会省略“零”年份

declare @YEAR1 as date = '20110101';
declare @YEAR2 as date = '20190101';

WITH YEARS AS (SELECT @YEAR1 y
               UNION ALL
               SELECT dateadd(year,1,y) FROM YEARS WHERE y < @YEAR2)
    SELECT YEARS.y,count(0) YearStartActiveOrders FROM YourTable 
         CROSS JOIN YEARS 
       WHERE YEARS.y BETWEEN CAST(orderdate as date) 
                 AND CAST(DATEADD(mm, BindingTime, OrderDate) as date)
                      GROUP BY Years.y

答案 1 :(得分:0)

好像您需要的是一个日期表(具有一年中所有天的列表),并让该表与您的分组数据(一年中的每天的活动订单数)结合在一起。

您可以使用this date table from Aaron Bertrand。我使用以下参数生成了#dim表,仅生成了两年数据(2015年,2016年):

DECLARE @StartDate DATE = '20150101', @NumberOfYears INT = 2;

然后您可以执行以下操作:

with ordertable as
(
 select 1 as orderid, '20160101' as orderdate, 2 as bindingtime union all
 select 2, '20160305', 3 union all
 select 3, '20160305', 5 union all
 select 4, '20150305', 5
)
select d.year, isnull(count(orderid), 0) nrActiveOrdersFirstDayOfYear
from #dim d 
     left join ordertable g on d.year = year(g.orderdate) 
                               and g.orderdate = d.date 
                               and d.FirstOfYear between g.orderdate and DATEADD(mm, g.bindingtime, OrderDate)
group by d.year 

以我作为示例的样本数据,您将得到结果:

year    nrActiveOrdersFirstDayOfYear
2015    0
2016    1

正在运行的演示here