SQL仅包括AVG计算中的工作时间

时间:2016-01-21 13:26:20

标签: sql sql-server sql-server-2012

我看了一下论坛,但是找不到任何足够的内容适合我的场景,所以这里就是这样。

我有以下查询,该查询计算在定义的日期期间内跨多个表的一组条目的平均时间。 3种类型(IR,SR,CR)都链接到一个表(WorkItems)。我平均时间的查询如下。 (参数用于报告服务和日期选择器)

Select 
WIAvgAssign = AVG(
Case When WI.id Like 'IR%' Then DATEDIFF(hour,wi.CreatedDate,IR.FirstAssignedDate)
When WI.Id Like 'SR%' Then DATEDIFF(hour,wi.CreatedDate,SR.FirstAssignedDate)
When WI.Id Like 'SR%' Then DATEDIFF(hour,wi.CreatedDate,CR.FirstAssignedDate)
END),
IRAvgAssign = AVG(DATEDIFF(hour,wi.CreatedDate,IR.FirstAssignedDate)),
SRAvgAssign = AVG(DATEDIFF(hour,wi.CreatedDate,SR.FirstAssignedDate)),
CRAvgAssign = AVG(DATEDIFF(hour,wi.CreatedDate,CR.FirstAssignedDate))
from WorkItemDimvw WI
Left Outer Join IncidentDimvw IR on WI.EntityDimKey=IR.EntityDimKey
Left Outer Join ServiceRequestDimvw SR on WI.EntityDimKey=SR.EntityDimKey
Left Outer Join ChangeRequestDimvw CR on WI.EntityDimKey=CR.EntityDimKey
Where (IR.ResolvedDate >= @StartDate AND IR.ResolvedDate < @EndDate) OR
(SR.CompletedDate >= @StartDate AND SR.CompletedDate < @EndDate) OR
(CR.ActualEndDate >=@StartDate AND CR.ActualEndDate < @EndDate)

我有一张表格,其中包含每周的每一天以及该特定日期的营业时间(日期是创建条目的时间,它只是我感兴趣的时间),周末的价值是空白的。

Day          Start Time                  End Time
Monday       2014-03-06 09:00:00.000     2014-03-06 17:00:00.000
Tuesday      2014-03-06 09:00:00.000     2014-03-06 17:00:00.000
Wednesday    2014-03-06 09:00:00.000     2014-03-06 17:00:00.000
Thursday     2014-03-06 09:00:00.000     2014-03-06 17:00:00.000
Friday       2014-03-06 09:00:00.000     2014-03-06 17:00:00.000
Saturday     NULL                        NULL
Sunday       NULL                        NULL

我目前获得的平均小时数与营业时间无关,因此我希望能够在办公室关闭时剥离并提供更准确的平均值。

由于

编辑 - 我已经提出了这个问题,因为我已经在查询中手动指定了非工作时间的数量并在周末的计算中添加了,所以效率有点低。看一下个人记录,我认为这是正确的。我暂时取出了CR计算

Declare @StartDate datetime
Declare @EndDate datetime
Set @StartDate = '2015/01/01'
Set @EndDate = '2015/12/31'
Select
AVG(
CASE WHEN CAST(wi.createddate as date) = 
CAST(
CASE
WHEN WI.Id like 'IR%' then CASE WHEN ir.FirstAssignedDate !=NULL THEN ir.firstassigneddate else GETDATE() END
WHEN WI.Id like 'SR%' then CASE WHEN sr.firstassigneddate !=NULL THEN Sr.firstassigneddate else GETDATE() END
END
as date)
THEN DATEDIFF(HOUR,wi.CreatedDate,
CASE
WHEN WI.Id like 'IR%' then CASE WHEN ir.FirstAssignedDate !=NULL THEN ir.firstassigneddate else GETDATE() END
WHEN WI.Id like 'SR%' then CASE WHEN sr.firstassigneddate !=NULL THEN Sr.firstassigneddate else GETDATE() END
END)
ELSE (DATEDIFF(hour,wi.CreatedDate,DATEADD(hour,-15*DATEDIFF(day,wi.CreatedDate,CASE
WHEN WI.Id like 'IR%' then CASE WHEN ir.FirstAssignedDate !=NULL THEN ir.firstassigneddate else GETDATE() END
WHEN WI.Id like 'SR%' then CASE WHEN sr.firstassigneddate !=NULL THEN Sr.firstassigneddate else GETDATE() END
END),CASE
WHEN WI.Id like 'IR%' then CASE WHEN ir.FirstAssignedDate !=NULL THEN ir.firstassigneddate else GETDATE() END
WHEN WI.Id like 'SR%' then CASE WHEN sr.firstassigneddate !=NULL THEN Sr.firstassigneddate else GETDATE() END
END)))-48*DATEDIFF(wk,wi.CreatedDate,CASE
WHEN WI.Id like 'IR%' then CASE WHEN ir.FirstAssignedDate !=NULL THEN ir.firstassigneddate else GETDATE() END
WHEN WI.Id like 'SR%' then CASE WHEN sr.firstassigneddate !=NULL THEN Sr.firstassigneddate else GETDATE() END
END)
END)
from WorkItemDimvw WI
Left Outer Join IncidentDimvw IR on WI.EntityDimKey=IR.EntityDimKey
Left Outer Join ServiceRequestDimvw SR on WI.EntityDimKey=SR.EntityDimKey
Left Outer Join ChangeRequestDimvw CR on WI.EntityDimKey=CR.EntityDimKey
WHERE (wi.Id like 'IR%' or WI.ID like 'SR%') AND
((IR.ResolvedDate >=@StartDate AND IR.ResolvedDate < @EndDate) OR
(Sr.CompletedDate >=@StartDate AND SR.CompletedDate < @EndDate))

2 个答案:

答案 0 :(得分:1)

经过多个小时的调整后,我想出了以下内容,我90%肯定是对的。如果有任何方法可以优化查询,那将会有所帮助。

Declare @StartDate datetime
Declare @EndDate datetime
Set @StartDate = '2016/01/01'
Set @EndDate = '2016/12/31'

SELECT  
   WIAvgAssign = AVG(
        Case 
            When id Like 'IR%' Then DATEDIFF(hour,NormalizedCreatedDate,NormalizedIRAssignedDate)
            -(DATEDIFF(wk,normalizedcreateddate,NormalizedIRAssignedDate)*48)
            -((DATEDIFF(day,normalizedcreateddate,NormalizedIRAssignedDate)-(DATEDIFF(wk,normalizedcreateddate,NormalizedIRAssignedDate)*2))*14)
            -(Case When DateName(dw,NormalizedCreatedDate) = 'Sunday' THEN 24 ELSE 0 END)
            -(Case When DATENAME(dw,NormalizedIRAssignedDate) = 'Saturday' THEN 24 ELSE 0 END)
            When id Like 'SR%' Then DATEDIFF(hour,NormalizedCreatedDate,NormalizedSRAssignedDate)
            -(DATEDIFF(wk,normalizedcreateddate,NormalizedSRAssignedDate)*48)
            -((DATEDIFF(day,normalizedcreateddate,NormalizedSRAssignedDate)-(DATEDIFF(wk,normalizedcreateddate,NormalizedSRAssignedDate)*2))*14)
            -(Case When DateName(dw,NormalizedCreatedDate) = 'Sunday' THEN 24 ELSE 0 END)
            -(Case When DATENAME(dw,NormalizedSRAssignedDate) = 'Saturday' THEN 24 ELSE 0 END)
            When id Like 'CR%' Then DATEDIFF(hour,NormalizedCreatedDate,NormalizedCRAssignedDate)
            -(DATEDIFF(wk,normalizedcreateddate,NormalizedCRAssignedDate)*48)
            -((DATEDIFF(day,normalizedcreateddate,NormalizedCRAssignedDate)-(DATEDIFF(wk,normalizedcreateddate,NormalizedCRAssignedDate)*2))*14)
            -(Case When DateName(dw,NormalizedCreatedDate) = 'Sunday' THEN 24 ELSE 0 END)
            -(Case When DATENAME(dw,NormalizedCRAssignedDate) = 'Saturday' THEN 24 ELSE 0 END)
        END),
    IRAvgAssign = AVG(DATEDIFF(hour,NormalizedCreatedDate,NormalizedIRAssignedDate)
            -(DATEDIFF(wk,normalizedcreateddate,NormalizedIRAssignedDate)*48)
            -((DATEDIFF(day,normalizedcreateddate,NormalizedIRAssignedDate)-(DATEDIFF(wk,normalizedcreateddate,NormalizedIRAssignedDate)*2))*14)
            -(Case When DateName(dw,NormalizedCreatedDate) = 'Sunday' THEN 24 ELSE 0 END)
            -(Case When DATENAME(dw,NormalizedIRAssignedDate) = 'Saturday' THEN 24 ELSE 0 END)),
    SRAvgAssign = AVG(DATEDIFF(hour,NormalizedCreatedDate,NormalizedSRAssignedDate)
            -(DATEDIFF(wk,normalizedcreateddate,NormalizedSRAssignedDate)*48)
            -((DATEDIFF(day,normalizedcreateddate,NormalizedSRAssignedDate)-(DATEDIFF(wk,normalizedcreateddate,NormalizedSRAssignedDate)*2))*14)
            -(Case When DateName(dw,NormalizedCreatedDate) = 'Sunday' THEN 24 ELSE 0 END)
            -(Case When DATENAME(dw,NormalizedSRAssignedDate) = 'Saturday' THEN 24 ELSE 0 END)),
    CRAvgAssign = AVG(DATEDIFF(hour,NormalizedCreatedDate,NormalizedCRAssignedDate)
            -(DATEDIFF(wk,normalizedcreateddate,NormalizedCRAssignedDate)*48)
            -((DATEDIFF(day,normalizedcreateddate,NormalizedCRAssignedDate)-(DATEDIFF(wk,normalizedcreateddate,NormalizedCRAssignedDate)*2))*14)
            -(Case When DateName(dw,NormalizedCreatedDate) = 'Sunday' THEN 24 ELSE 0 END)
            -(Case When DATENAME(dw,NormalizedCRAssignedDate) = 'Saturday' THEN 24 ELSE 0 END))
FROM (
        Select WI.id, 
            CASE 
                WHEN wi.CreatedDate < DATEADD(HOUR, 9, CAST(CAST(wi.CreatedDate AS DATE) AS DATETIME))
                THEN DATEADD(HOUR, 9, CAST(CAST(wi.CreatedDate AS DATE) AS DATETIME))
                ELSE wi.CreatedDate
            END NormalizedCreatedDate,
            CASE
        WHEN IR.FirstAssignedDate !=NULL THEN CASE
                WHEN IR.FirstAssignedDate > DATEADD(HOUR, 17, CAST(CAST(IR.FirstAssignedDate AS DATE) AS DATETIME))
                THEN DATEADD(HOUR, 17, CAST(CAST(IR.FirstAssignedDate AS DATE) AS DATETIME))
                ELSE IR.FirstAssignedDate END 
        ELSE CASE WHEN IR.ResolvedDate > DATEADD(HOUR, 17, CAST(CAST(IR.ResolvedDate AS DATE) AS DATETIME))
                THEN DATEADD(HOUR, 17, CAST(CAST(IR.ResolvedDate AS DATE) AS DATETIME))
                ELSE IR.ResolvedDate END
            END NormalizedIRAssignedDate,
                        CASE
        WHEN SR.FirstAssignedDate !=NULL THEN CASE
                WHEN SR.FirstAssignedDate > DATEADD(HOUR, 17, CAST(CAST(SR.FirstAssignedDate AS DATE) AS DATETIME))
                THEN DATEADD(HOUR, 17, CAST(CAST(SR.FirstAssignedDate AS DATE) AS DATETIME))
                ELSE SR.FirstAssignedDate END 
        ELSE CASE WHEN SR.CompletedDate > DATEADD(HOUR, 17, CAST(CAST(SR.CompletedDate AS DATE) AS DATETIME))
                THEN DATEADD(HOUR, 17, CAST(CAST(SR.CompletedDate AS DATE) AS DATETIME))
                ELSE SR.CompletedDate END
            END NormalizedSRAssignedDate,
            CASE
        WHEN CR.FirstAssignedDate !=NULL THEN CASE
                WHEN CR.FirstAssignedDate > DATEADD(HOUR, 17, CAST(CAST(CR.FirstAssignedDate AS DATE) AS DATETIME))
                THEN DATEADD(HOUR, 17, CAST(CAST(CR.FirstAssignedDate AS DATE) AS DATETIME))
                ELSE CR.FirstAssignedDate END 
        ELSE CASE WHEN CR.ActualEndDate > DATEADD(HOUR, 17, CAST(CAST(CR.ActualEndDate AS DATE) AS DATETIME))
                THEN DATEADD(HOUR, 17, CAST(CAST(CR.ActualEndDate AS DATE) AS DATETIME))
                ELSE CR.ActualEndDate END
            END NormalizedCRAssignedDate
        from WorkItemDimvw WI
            Left Outer Join IncidentDimvw IR 
            on WI.EntityDimKey=IR.EntityDimKey
            Left Outer Join ServiceRequestDimvw SR 
            on WI.EntityDimKey=SR.EntityDimKey
            Left Outer Join ChangeRequestDimvw CR 
            on WI.EntityDimKey=CR.EntityDimKey
        Where (
                (IR.ResolvedDate >= @StartDate AND IR.ResolvedDate < @EndDate) 
                OR (SR.CompletedDate >= @StartDate AND SR.CompletedDate < @EndDate) 
                OR (CR.ActualEndDate >= @StartDate AND CR.ActualEndDate < @EndDate)
            )
    ) dataset

编辑 - 显然我们并没有排除下午5点之后的时间(在我的例子中它是8到6之间,因为这是我的客户想要的)所以我在计算中添加了每天删除14小时(除了周末)项目是开放的,它给了我我认为的确切数字

答案 1 :(得分:0)

这对我来说是一个有趣的问题。我对这个方法采取了一些措施:

  1. CreatedDate总是在FirstAssignedDate
  2. 之前发生
  3. SET DATEFIRST 7(如果不同则更改工作日数字)
  4. 如果是周末,可以过滤CreatedDateFirstAssignedDate
  5. 这是我的方法,我确信它的效率非常低,但这是我的第一个想法:

    SELECT  
        WIAvgAssign = AVG(
            Case 
                When id Like 'IR%' Then DATEDIFF(hour,NormalizedCreatedDate,NormalizedIRAssignedDate)
                When id Like 'SR%' Then DATEDIFF(hour,NormalizedCreatedDate,NormalizedSRAssignedDate)
                When id Like 'SR%' Then DATEDIFF(hour,NormalizedCreatedDate,NormalizedCRAssignedDate)
            END
        ),
        IRAvgAssign = AVG(DATEDIFF(hour,NormalizedCreatedDate,NormalizedIRAssignedDate)),
        SRAvgAssign = AVG(DATEDIFF(hour,NormalizedCreatedDate,NormalizedSRAssignedDate)),
        CRAvgAssign = AVG(DATEDIFF(hour,NormalizedCreatedDate,NormalizedCRAssignedDate))
    FROM (
            Select WI.id, 
                CASE 
                    WHEN wi.CreatedDate < DATEADD(HOUR, 9, CAST(CAST(wi.CreatedDate AS DATE) AS DATETIME))
                    THEN DATEADD(HOUR, 9, CAST(CAST(wi.CreatedDate AS DATE) AS DATETIME))
                    ELSE wi.CreatedDate
                END NormalizedCreatedDate,
                CASE 
                    WHEN IR.FirstAssignedDate > DATEADD(HOUR, 17, CAST(CAST(IR.FirstAssignedDate AS DATE) AS DATETIME))
                    THEN DATEADD(HOUR, 17, CAST(CAST(IR.FirstAssignedDate AS DATE) AS DATETIME))
                    ELSE IR.FirstAssignedDate
                END NormalizedIRAssignedDate,
                CASE 
                    WHEN SR.FirstAssignedDate > DATEADD(HOUR, 17, CAST(CAST(SR.FirstAssignedDate AS DATE) AS DATETIME))
                    THEN DATEADD(HOUR, 17, CAST(CAST(SR.FirstAssignedDate AS DATE) AS DATETIME))
                    ELSE SR.FirstAssignedDate
                END NormalizedSRAssignedDate,
                CASE 
                    WHEN CR.FirstAssignedDate > DATEADD(HOUR, 17, CAST(CAST(CR.FirstAssignedDate AS DATE) AS DATETIME))
                    THEN DATEADD(HOUR, 17, CAST(CAST(CR.FirstAssignedDate AS DATE) AS DATETIME))
                    ELSE CR.FirstAssignedDate
                END NormalizedCRAssignedDate
            from WorkItemDimvw WI
                Left Outer Join IncidentDimvw IR 
                on WI.EntityDimKey=IR.EntityDimKey
                Left Outer Join ServiceRequestDimvw SR 
                on WI.EntityDimKey=SR.EntityDimKey
                Left Outer Join ChangeRequestDimvw CR 
                on WI.EntityDimKey=CR.EntityDimKey
                --AVOID SATURDAYS and SUNDAYS in result set
                --Also assumes SET DATEFIRST 7
            Where DATEPART(WEEKDAY,wi.CreatedDate) NOT IN (1,7) 
                AND DATEPART(WEEKDAY,IR.FirstAssignedDate) NOT IN (1,7)
                AND DATEPART(WEEKDAY,SR.FirstAssignedDate) NOT IN (1,7)
                AND DATEPART(WEEKDAY,CR.FirstAssignedDate) NOT IN (1,7)
                AND(
                    (IR.ResolvedDate >= @StartDate AND IR.ResolvedDate < @EndDate) 
                    OR (SR.CompletedDate >= @StartDate AND SR.CompletedDate < @EndDate) 
                    OR (CR.ActualEndDate >= @StartDate AND CR.ActualEndDate < @EndDate)
                )
        ) dataset
    

    所以我基本上只检查CreatedDate&lt;当天0900,如果是这样的话,将时间设置为0900,然后检查FirstAssignedDate&gt;如果是这样的话,当天1700并将时间设置为1700。如果他们在周末,我也会过滤掉所有CreatedDateFirstAssignedDate

    编辑:

    我更新了我原来的帖子。我更改了日期检查以使用DATEADD而不是构建字符串并尝试将字符串转换为DATETIME