获取日期差异,然后在其间的每个月中添加 1

Posted

技术标签:

【中文标题】获取日期差异,然后在其间的每个月中添加 1【英文标题】:Get date diff then add 1 to each month in between 【发布时间】:2018-09-26 07:34:31 【问题描述】:

我们试图做的是准确表示一个月内的典型订单量。 接下来的每个月(包括订单打开的月份)该订单的计数都为 1,直到它被关闭。 所以例如2017 年 2 月创建了 2 个订单,因此 2 月的计数为 2。对于订单号。 4,六月之后的每个月,该特定订单的计数都为 1。

WAREHOUSENO ORDERNO ORDER DATE  CLOSED DATE
1           ABC     2/22/17      3/10/17
2           DEF     2/23/17      4/1/17
1           GHI     3/1/17       3/28/17
3           JKL     6/1/17  
2           MNO     9/1/17       10/12/17
3           PQR     10/22/17     2/23/18
1           STU     12/5/17      12/28/17
2           VWX     2/8/18  
3           YZ      3/15/18

最后,我们想汇总每个月的所有计数,按仓库和年份分组。

     Month                                          
     WAREHOUSE    Jan   Feb   Mar  Apr  May Jun Jul Aug Sep Oct Nov Dec
         1          0    1     1     0   0    0  0   0   0   0   0   1
2017     2          0    1     1     0   0    0  0   0   1   1   0   0
         3          0    0     0     0   0    1  1   1   1   2   2   2
TOTAL OPEN               2     2              1  1   1   2   3   2   3

         1          0     0    0     0                          
2018     2          1     1    1     1    
         3          1     1    2     2    
TOTAL OPEN          2     1    3     3

真的很感激这个方向!

【问题讨论】:

在我看来,您的问题过于宽泛,因为所需的输出是一种报告,而 sql-server 可以提供查询但不能提供报告。 请编辑您的帖子以将其缩小到 TSQL 足以/适当的特定问题。您可以使用pivot et al. 来获得所需的计数,但尝试在 SSMS 中进行最终演示并不是一个好主意;相反,您应该为此使用报告前端。 这里至少可以说有很多挑战。为什么您的输出从 2017 年 1 月开始?您没有该月的数据。为什么它会在 2018 年 4 月结束?再一次......那个月没有数据。您将需要一个计数表或日历表来执行此操作,因为您希望在可用数据之外返回数据。返回数据并不是什么大问题,但格式属于表示层,而不是数据库。这是一个很好的起点。spaghettidba.com/2015/04/24/… 感谢您的意见。我是新来在这里发布有关 T-SQL 的问题,所以这些方向对未来很有帮助。 【参考方案1】:
create table sampleData
(
    warehouseNo int not null
    ,orderNo nvarchar(5) not null
    , orderDate DateTime not null
    , closedDate DateTime
)

insert sampleData (warehouseNo, orderNo, orderDate, closedDate)
values (1 ,'ABC', '2017-02-22', '2017-03-10')
,      (2 ,'DEF', '2017-02-23', '2017-04-01')
,      (1 ,'GHI', '2017-03-01', '2017-03-28')
,      (3 ,'JKL', '2017-06-01', null)
,      (2 ,'MNO', '2017-09-01', '2017-10-12')
,      (3 ,'PQR', '2017-10-22', '2018-02-23')
,      (1 ,'STU', '2017-12-05', '2017-12-28')
,      (2 ,'VWX', '2018-02-08', null)  
,      (3 ,'YZ',  '2018-03-15', null)



SELECT ISNULL(CONVERT(CHAR(5), year(orderDate)), 'Total') AS [YEAR]
        ,ISNULL(warehouseNo, '') AS [Warehouse]
        ,count(CASE WHEN MONTH(orderDate) = 1 THEN orderNo END) AS JAN
        ,count(CASE WHEN MONTH(orderDate) = 2 THEN orderNo END) AS FEB
        ,count(CASE WHEN MONTH(orderDate) = 3 THEN orderNo END) AS MAR
        ,count(CASE WHEN MONTH(orderDate) = 4 THEN orderNo END) AS APR
        ,count(CASE WHEN MONTH(orderDate) = 5 THEN orderNo END) AS MAY
        ,count(CASE WHEN MONTH(orderDate) = 6 THEN orderNo END) AS JUN
        ,count(CASE WHEN MONTH(orderDate) = 7 THEN orderNo END) AS JUL
        ,count(CASE WHEN MONTH(orderDate) = 8 THEN orderNo END) AS AUG
        ,count(CASE WHEN MONTH(orderDate) = 9 THEN orderNo END) AS SEP
        ,count(CASE WHEN MONTH(orderDate) = 10 THEN orderNo END) AS OCT
        ,count(CASE WHEN MONTH(orderDate) = 11 THEN orderNo END) AS NOV
        ,count(CASE WHEN MONTH(orderDate) = 12 THEN orderNo END) AS DEC
    FROM sampleData
    GROUP BY ROLLUP(year(orderDate), warehouseNo)
        --order by ISNULL(CONVERT(char(5),year(orderDate)),'Total')

【讨论】:

【参考方案2】:

您是否每个月都在清点每个仓库的未结订单?如果是这样,我相信下面的代码会满足您的要求:

declare @sampleData table
(
    warehouseNo int not null
    ,orderNo nvarchar(5) not null
    , orderDate DateTime not null
    , closedDate DateTime
)

insert @sampleData (warehouseNo, orderNo, orderDate, closedDate)
values (1 ,'ABC', '2017-02-22', '2017-03-10')
,      (2 ,'DEF', '2017-02-23', '2017-04-01')
,      (1 ,'GHI', '2017-03-01', '2017-03-28')
,      (3 ,'JKL', '2017-06-01', null)
,      (2 ,'MNO', '2017-09-01', '2017-10-12')
,      (3 ,'PQR', '2017-10-22', '2018-02-23')
,      (1 ,'STU', '2017-12-05', '2017-12-28')
,      (2 ,'VWX', '2018-02-08', null)  
,      (3 ,'YZ',  '2018-03-15', null)

declare @start datetime 
, @end datetime

select @start = dateadd(day,1-day(min(orderDate)),min(orderDate))
, @end = max(coalesce(closedDate, getutcdate()))
from @sampleData

;with allDates as 
(
    select @start FirstOfMonth

    union all

    select dateadd(month,1,FirstOfMonth) 
    from allDates
    where FirstOfMonth <= @end
)
, normalisedDates as --round all dates down to first of the month since we only care about month and year; not day
(
    select warehouseNo
    , dateadd(day,1 - datepart(day, orderDate), orderDate) orderDate
    , dateadd(day,1 - datepart(day, coalesce(closedDate, getutcdate())), coalesce(closedDate, getutcdate())) closedDate
    from @sampleData
)
select ad.FirstOfMonth
, nd.warehouseNo 
, count(nd.warehouseNo) OpenOrderCount
from allDates ad
left outer join normalisedDates nd
on ad.FirstOfMonth between nd.orderDate and nd.closedDate
group by ad.FirstOfMonth, nd.warehouseNo
order by ad.FirstOfMonth, nd.warehouseNo

SQL Fiddle Example


更新

关于您关于按月旋转的问题;当然。

有关旋转的精彩文章请参见此处:https://blog.sqlauthority.com/2008/06/07/sql-server-pivot-and-unpivot-table-examples/

有关您的方案的代码,请参见下文:

declare @start datetime 
, @end datetime

select @start = dateadd(day,1-day(min(orderDate)),min(orderDate))
, @end = max(coalesce(closedDate, getutcdate()))
from @sampleData

;with allDates as 
(
    select @start FirstOfMonth

    union all

    select dateadd(month,1,FirstOfMonth) 
    from allDates
    where FirstOfMonth <= @end
)
, normalisedDates as --round all dates down to first of the month since we only care about month and year; not day
(
    select warehouseNo
    , dateadd(day,1 - datepart(day, orderDate), orderDate) orderDate
    , dateadd(day,1 - datepart(day, coalesce(closedDate, getutcdate())), coalesce(closedDate, getutcdate())) closedDate
    from @sampleData
)
select warehouseNo, [1] Jan, [2] Feb, [3] Mar, [4] Apr, [5] May, [6] Jun, [7] Jul, [8] Aug, [9] Sep, [10] Oct, [11] Nov, [12] Dec
from 
(
    select datepart(month,ad.FirstOfMonth) MonthX
    , nd.warehouseNo 
    , count(nd.warehouseNo) OpenOrderCount
    from allDates ad
    left outer join normalisedDates nd
    on ad.FirstOfMonth between nd.orderDate and nd.closedDate
    group by ad.FirstOfMonth, nd.warehouseNo
) x
pivot 
(
    sum(OpenOrderCount) for MonthX in ([1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12]) 
) p
order by warehouseNo

【讨论】:

这几乎让我到达了我需要去的地方。有没有办法以月为列并按仓库计算每个未结订单的计数来透视表?

以上是关于获取日期差异,然后在其间的每个月中添加 1的主要内容,如果未能解决你的问题,请参考以下文章

Python:月中2个日期时间的差异[重复]

如何比较日期和时间并获取差异,然后在 Javascript 中将其设置为秒

Moment js按星期和星期几获取一个月中的特定日期

Kotlin:获取两个日期之间的差异(现在和以前的日期)

如何在mongoDB中获取日期差异?日期应该是天数的差异?

如何使用 SQL 获取 2 列之间日期差异的计数(值的分布)?