如何获取当月关闭的上个月的日期

时间:2014-06-11 07:04:38

标签: sql sql-server-2008 reporting-services

我使用SSRS报告构建器应用程序为我的系统创建BI报告,该报告跟踪每个月记录和关闭的事件数。

以下是我需要创建查询的表

Month      Logged  Received  Closed  Remaining
January    200     220       150     70
February   150     220       200     20
March      110     130       100     30
April      200     230       200     30

,每列定义如下:

已记录=当前月份的未结事件,例如2014年1月1日至2014年1月31日期间开放(仅包含当前月份数据)

收到=记录事件+前几个月的剩余时间仍未结束,例如月份febreuary将为150当前飞蛾+上一个月剩余70将给我总共220收到。

已关闭=在当月开立并在当月结束的事件+本月结束的上个月的剩余事件

剩余=已收到 - 已关闭

我使用的代码并没有给我前几个月的紧急事件,也只是给了我当月关闭的事件

以下是我用于查询的代码:

SELECT  group_id, YEAR(Opendate) AS Year, MONTH(Opendate) AS Month,
        COUNT(CASE WHEN Month(Closedate) = Month(Opendate)
            AND Month(closedate)> Month (opendate) THEN 1 ELSE NULL END) AS closed, 
        COUNT(*) AS Logged, 
FROM    Incidents
WHERE   (Opendate >= @YearStart) AND (Opendate <= @YearEnd)
GROUP BY YEAR(Opendate), MONTH(Opendate), group_id
ORDER BY Year, Month,group_id 

记录正常工作已关闭,收到并且剩下我被卡住了。


我尝试使用Union并获取了记录和关闭数据

Select count(*) logged,year(opendate) as year1,MONTH(opendate) as 
month1,'Logged' as status1
From Incidents 
where opendate is not null 
GROUP BY year(opendate),MONTH(opendate)
UNION 
Select count(*) closed,year(Closedate) as year1,MONTH(Closedate) as 
month1,'All_Closed' as status1
From Incidents 
where Closedate is not null
GROUP BY year(Closedate),MONTH(Closedate)
UNION 
Select count(*) Remaining,year(opendate) as year1,MONTH(opendate) as 
month1,'Current_Month_Not_Closed' as status1
From Incidents 
where Month(Closedate) > MONTH(Opendate)
GROUP BY year(opendate),MONTH(opendate)
UNION 
Select count(*) Month_Closed,year(opendate) as year1,MONTH(opendate) as 
month1,'Current_Month_Close' as status1
From Incidents 
where MONTH(Closedate) = MONTH(Opendate)  
GROUP BY year(opendate),MONTH(opendate)
order by year1,month1

我收到的数据如下:

logged | year1 | month1 | status1
-------+-------+--------+-------------------------
  1093 |  2014 |      1 | Logged
  1089 |  2014 |      1 | All_Closed
   997 |  2014 |      1 | Current_Month_Close
    96 |  2014 |      1 | Current_Month_Not_Closed
  1176 |  2014 |      2 | Logged
  1176 |  2014 |      2 | All_Closed
    91 |  2014 |      2 | Current_Month_Not_Closed
  1085 |  2014 |      2 | Current_Month_Close
  1340 |  2014 |      3 | Logged
  1327 |  2014 |      3 | All_Closed
   107 |  2014 |      3 | Current_Month_Not_Closed
  1232 |  2014 |      3 | Current_Month_Close
   116 |  2014 |      4 | Current_Month_Not_Closed
  1320 |  2014 |      4 | Current_Month_Close
  1424 |  2014 |      4 | All_Closed
  1441 |  2014 |      4 | Logged
  1167 |  2014 |      5 | Current_Month_Close
   105 |  2014 |      5 | Current_Month_Not_Closed
  1277 |  2014 |      5 | Logged
  1283 |  2014 |      5 | All_Closed

2 个答案:

答案 0 :(得分:0)

收到的是在月底之前开设的门票数量,并且在月初之前没有关闭。

count(case when OpenDate <= @EndOfMonth and 
                (@StartOfMonth >= CloseDate or CloseDate is null) then 1 end)
    as Received

关闭非常简单:

count(case when CloseDate between @StartOfMonth and @EndOfMonth 
                then 1 end) as Closed

您应该能够弄清楚如何使用Google计算一个月的开始和结束时间。

答案 1 :(得分:0)

要获得可靠的数据,日历表作为主播可以提供帮助,如果票证可以在开放日期之后的几个月内存活,或者可能有一个月没有创建票证,则需要这样做。

例如假数据

CREATE TABLE Incidents (
  id int identity(1, 1)
, group_id nvarchar(100)
, Opendate Datetime
, Closedate Datetime
)

INSERT INTO Incidents
VALUES ('Service Desk', '20140107', '20140120')
     , ('Service Desk', '20140117', '20140123')
     , ('Service Desk', '20140127', '20140313')
     , ('Service Desk', '20140310', '')
-- from an OP comment the open tickets have the Closedate '' (1900-01-01)

没有日历表(或临时或CTE),即使第三个记录在该月份都是“已接收”和“剩余”,也无法在结果集中添加二月。

要创建日历,有几种方法,在这种情况下,我们需要一些有关月份的信息,但不需要关于日期,因此不会生成这些日期。

declare @YearStart date = '20140101'
declare @YearEnd date = '20140430'

;WITH D(N) AS (
          SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 
UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 
UNION ALL SELECT 8 UNION ALL SELECT 9
)
SELECT EOM
     = DATEADD(D, -1, DATEADD(M, u.N + 10 * t.N + 1
             , DATEADD(Y, DATEDIFF(Y, 0, @YearStart), 0)))
     , pMonth = u.N + 10 * t.N
FROM   D u
       CROSS JOIN D t
WHERE  u.N + 10 * t.N <= DATEDIFF(M, @YearStart, @YearEnd)

此处EOM是月末的日期,它将用于检查事件是否在月中关闭,pMonth是从@YearStart开始的渐进月。< / p>

现在我们需要准备要使用的事件表中的数据

SELECT ID
     , OpenDate
     , Closedate = COALESCE(NULLIF(Closedate, ''), '99991231')
     , pOpenDate = DATEDIFF(M, @YearStart, OpenDate)
     , pClosedate = DATEDIFF(M, @YearStart
                  , COALESCE(NULLIF(Closedate, ''), '99991231'))
FROM   Incidents

Closedate需要始终具有高于OpenDate的值,因为常量日期为9999-12-31pOpenDatepClosedate,因为{{1}之前,是@ pMonthOpenDate分别从@YearStart开始的渐进月。

将这些内容设置为可以创建主查询

Closedate

SQLFiddle Demo

使用declare @YearStart date = '20140101' declare @YearEnd date = '20140430' ;WITH D(N) AS ( SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 ), CM AS ( SELECT EOM = DATEADD(D, -1, DATEADD(M, u.N + 10 * t.N + 1 , DATEADD(Y, DATEDIFF(Y, 0, @YearStart), 0))) , pMonth = u.N + 10 * t.N FROM D u CROSS JOIN D t WHERE u.N + 10 * t.N <= DATEDIFF(M, @YearStart, @YearEnd) ), I AS ( SELECT ID , OpenDate , Closedate = COALESCE(NULLIF(Closedate, ''), '99991231') , pOpenDate = DATEDIFF(M, @YearStart, OpenDate) , pClosedate = DATEDIFF(M, @YearStart , COALESCE(NULLIF(Closedate, ''), '99991231')) FROM Incidents ) SELECT MONTH(CM.EOM) [Month] , Logged = SUM(CASE WHEN pOpenDate = pMonth THEN 1 ELSE 0 END) , Received = Count(i.id) , Closed = SUM(CASE WHEN pClosedate = pMonth AND i.Closedate < CM.EOM THEN 1 ELSE 0 END) , Remaining = SUM(CASE WHEN i.Closedate > CM.EOM THEN 1 ELSE 0 END) FROM CM INNER JOIN I ON CM.pMonth BETWEEN i.pOpenDate AND i.pClosedate WHERE CM.EOM <= @YearEnd GROUP BY CM.EOM ORDER BY CM.EOM 从日历表中获取JOIN@YearStart之间的月份以及当月活动的所有事件。它们的属性是使用@YearEnd逻辑计算的,如果CASE,如果票证处于活动状态,则会收到它,因此不需要逻辑。

所有Received都可以在CASE逻辑

中进行转换
BIT

SQLFiddle Demo

位逻辑基于declare @YearStart date = '20140101' declare @YearEnd date = '20140430' ;WITH D(N) AS ( SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 ), CM AS ( SELECT EOM = DATEADD(D, -1, DATEADD(M, u.N + 10 * t.N + 1 , DATEADD(Y, DATEDIFF(Y, 0, @YearStart), 0))) , pMonth = u.N + 10 * t.N FROM D u CROSS JOIN D t WHERE u.N + 10 * t.N <= DATEDIFF(M, @YearStart, @YearEnd) ), I AS ( SELECT ID , OpenDate , Closedate = COALESCE(NULLIF(Closedate, ''), '99991231') , pOpenDate = DATEDIFF(M, @YearStart, OpenDate) , pClosedate = DATEDIFF(M, @YearStart , COALESCE(NULLIF(Closedate, ''), '99991231')) FROM Incidents ) SELECT MONTH(CM.EOM) [Month] , Logged = SUM(1 - CAST(pOpenDate - pMonth AS BIT)) , Received = Count(i.id) , Closed = SUM(1 - CAST(pClosedate - pMonth AS BIT)) , Remaining = SUM(0 + CAST(i.pClosedate / (CM.pMonth + 1) AS BIT)) FROM CM INNER JOIN I ON CM.pMonth BETWEEN i.pOpenDate AND i.pClosedate WHERE CM.EOM <= @YearEnd GROUP BY CM.EOM ORDER BY CM.EOM; CAST的工作方式:

  • 0转到0
  • 其他一切都归1

基于此(使用A和B整数):

    BIT 时,
  • 1 - CAST(A - B AS BIT)为1 {li> A = BCAST(A / (B + 1) AS BIT)时为{1 A > B强制隐式转换为0 +,因为INT不能BIT med)