获取日期差异,然后在其间的每个月中添加 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的主要内容,如果未能解决你的问题,请参考以下文章