SQL OVER(分区)问题 - 选择子集

时间:2015-06-13 22:18:18

标签: tsql aggregates

我试图使用" over(partition)"来获取特定的数据子集。句法。我已经创建了样本数据来说明。运行以下CTE会产生一个小的示例结果集。

我需要使用以下定义/伪代码计算2个日期范围 1:关闭天数=关闭日期,其中stat ='已关闭'减去由问题划分的opendate 2:解决天数=" ClosedDate,其中stat ='已解决'减去由问题划分的opendate。

我可以使用over(分区)语法获得#1,但我无法弄清楚#2。

with cte as 
(
select 114110712007835 as 'SRNumber', 214110712007835004 as ProblemNumber, 'Open' as 'Stat',    314110712007835004001 as TaskNumber, convert(datetime, '2015-03-02 19:47:43',120) as OpenDate,  convert(datetime, '2015-03-03 19:36:37',120) as CloseDate union 
select 114110712007835 as 'SRNumber',   214110712007835004 as ProblemNumber, 'Investigate' as 'stat',   314110712007835004002 as TaskNumber, convert(datetime, '2015-03-04 00:29:13',120)  as OpenDate, convert(datetime, '2015-03-05 19:36:34',120) as CloseDate  union 
select 114110712007835 as 'SRNumber',   214110712007835004 as ProblemNumber, 'Solve' as 'stat', 314110712007835004003 as TaskNumber, convert(datetime, '2015-03-06 18:17:13',120)  as OpenDate, convert(datetime, '2015-03-07 13:07:31',120) as CloseDate  union
select 114110712007835 as 'SRNumber',   214110712007835004 as ProblemNumber, 'Close' as 'stat', 315032012542588001001 as TaskNumber, convert(datetime, '2015-03-08 15:24:34',120)  as OpenDate, convert(datetime, '2015-03-09 15:15:42',120) as CloseDate  union
select 114110712007835 as 'SRNumber',   215032012542588001 as ProblemNumber, 'Open' as 'stat',  315032012542588001002 as TaskNumber, convert(datetime, '2015-04-20 20:05:48',120)  as OpenDate, convert(datetime, '2015-04-21 03:24:24',120) as CloseDate  union
select 114110712007835 as 'SRNumber',   215032012542588001 as ProblemNumber, 'Investigate' as 'stat',   315032012542588001003 as TaskNumber, convert(datetime, '2015-04-22 18:55:03',120)  as OpenDate, convert(datetime, '2015-04-23 03:24:28',120) as CloseDate  union
select 114110712007835 as 'SRNumber',   215032012542588001 as ProblemNumber, 'Solve' as 'stat', 315032012542588001004 as TaskNumber, convert(datetime, '2015-04-24 13:35:24',120)  as OpenDate, convert(datetime, '2015-04-27 02:24:31',120) as CloseDate union
select 114110712007835 as 'SRNumber',   215032012542588001 as ProblemNumber, 'Close' as 'stat', 315032012542588001004 as TaskNumber, convert(datetime, '2015-04-26 13:35:24',120)  as OpenDate, convert(datetime, '2015-04-29 03:24:31',120) as CloseDate
)

select srnumber, problemnumber, stat, opendate, closedate, --min(opendate) over(partition by problemnumber) as MinDate, max(closedate) over(partition by problemnumber) as MaxDate

case 
when stat = 'Solve' then datediff(mi,min(opendate) over(partition by problemnumber),max(closedate) over(partition by problemnumber)) 
else NULL end as Days_to_Solve

,datediff(mi,min(opendate) over(partition by problemnumber),max(closedate) over(partition by problemnumber))  as Days_to_Close


from cte
order by problemnumber asc, opendate asc
go   

2 个答案:

答案 0 :(得分:1)

子查询可以为您提供所需的结果。

SELECT  srnumber ,
            problemnumber ,
            stat ,
            opendate ,
            closedate , --min(opendate) over(partition by problemnumber) as MinDate, max(closedate) over(partition by problemnumber) as MaxDate
            ( CASE WHEN stat = 'Solve'
                   THEN ( SELECT TOP 1
                                    DATEDIFF(mi, MIN(opendate) OVER ( ),
                                                              MAX(closedate) OVER ( ))
                          FROM      cte c
                          WHERE     c.problemnumber = cte.problemnumber
                                    AND c.CloseDate <= cte.CloseDate
                        )
                   ELSE NULL
              END ) AS Days_to_Solve ,
            DATEDIFF(mi, MIN(opendate) OVER ( PARTITION BY problemnumber ),
                     MAX(closedate) OVER ( PARTITION BY problemnumber )) AS Days_to_Close
    FROM    cte
    ORDER BY problemnumber ASC ,
            opendate ASC

答案 1 :(得分:0)

我的结果非常类似于user1221684,但我使用的是Windows函数而不是子查询。所以我的答案应该更有效率,而且更简单。看看:

SELECT  *,
        DATEDIFF(   MI, --this is minutes. For days switch "MI" to "DAY"
                    MIN(CASE WHEN [Stat] = 'Open'  THEN OpenDate END) OVER (PARTITION BY problemNumber),
                    MIN(CASE WHEN [Stat] = 'Solve' THEN CloseDate END) OVER (PARTITION BY problemNumber)
                ) AS Minutes_To_Solve
        ,
        DATEDIFF(   MI, --this is minutes. For days switch "MI" to "DAY"
                    MIN(CASE WHEN [stat] = 'Open' THEN OpenDate  END) OVER (PARTITION BY problemNumber),
                    MIN(CASE WHEN [Stat] = 'Close'  THEN CloseDate END) OVER (PARTITION BY problemNumber)
                ) AS Minutes_To_Close
FROM CTE
ORDER BY OpenDate