SQL - AVG输出不正确

时间:2017-09-28 10:42:19

标签: sql sql-server vba sql-server-2008 average

在下面的查询中,我正在计算两个不同日期之间的提前期,并最终尝试获得提前期的平均值,但输出不正确。

SELECT
Round(AVG(CAST(
Case when CONVERT(datetime, ORDERDATE, 105) = CONVERT(datetime, INVOUTDATE, 105) THEN 0 else
Case when CONVERT(datetime, ORDERDATE, 105) + 1 = CONVERT(datetime, INVOUTDATE, 105) THEN 1 else
(DATEDIFF(dd, CONVERT(datetime, ORDERDATE, 105), CONVERT(datetime, INVOUTDATE, 105)))
-(DATEDIFF(wk, CONVERT(datetime, ORDERDATE, 105), CONVERT(datetime, INVOUTDATE, 105))*1)
-(CASE WHEN DATENAME(dw, CONVERT(datetime, ORDERDATE, 105)) = 'Sunday' THEN 1 ELSE 0 END)
-(CASE WHEN DATENAME(dw, CONVERT(datetime, INVOUTDATE, 105)) = 'Sunday' THEN 0 ELSE 0 END) end end AS FLOAT)),4) AS LEADTIME FROM DSORDERSTATUS
WHERE ORDERTYPE <> 'Exchange Order' 
AND CONVERT(datetime, ORDERDATE, 105) between '20170801' and '20170831' 
AND CONVERT(datetime, INVOUTDATE, 105) IS NOT NULL

要解决上述问题,我使用下面相同的查询提取数据,当我手动计算提前期时,平均值是正确的。 不知道问题出在哪里?有人可以告诉我我的查询是否有任何问题。 请点击链接以参考样本数据https://jsfiddle.net/samollason/uvqosxrr/3/

SELECT DISTINCT DOCKETNO,
Case when CONVERT(datetime, ORDERDATE, 105) = CONVERT(datetime, INVOUTDATE, 105) THEN 0 else
Case when CONVERT(datetime, ORDERDATE, 105) + 1 = CONVERT(datetime, INVOUTDATE, 105) THEN 1 else
(DATEDIFF(dd, CONVERT(datetime, ORDERDATE, 105), CONVERT(datetime, INVOUTDATE, 105)))
-(DATEDIFF(wk, CONVERT(datetime, ORDERDATE, 105), CONVERT(datetime, INVOUTDATE, 105))*1)
-(CASE WHEN DATENAME(dw, CONVERT(datetime, ORDERDATE, 105)) = 'Sunday' THEN 1 ELSE 0 END)
-(CASE WHEN DATENAME(dw, CONVERT(datetime, INVOUTDATE, 105)) = 'Sunday' THEN 0 ELSE 0 END) end end AS LEADTIME FROM DSORDERSTATUS
WHERE ORDERTYPE <> 'Exchange Order' 
AND CONVERT(datetime, ORDERDATE, 105) between '20170801' and '20170831' 
AND CONVERT(datetime, INVOUTDATE, 105) IS NOT NULL

3 个答案:

答案 0 :(得分:1)

好的,现在我明白了.. 我认为你必须按顺序分组以计算平均值

;with
S AS (      
    select DOCKETNO, ORDERDATE, INVOUTDATE, COUNT(*) n
    from DSORDERSTATUS where ORDERTYPE <> 'Exchange Order' 
    group by DOCKETNO, ORDERDATE, INVOUTDATE
),
D as (
    select [DOCKETNO], [ORDERDATE], [INVOUTDATE],
        DATEDIFF(dd, CONVERT(date, [ORDERDATE], 105), CONVERT(date, [INVOUTDATE], 105)) dd,
        DATEDIFF(wk, CONVERT(date, [ORDERDATE], 105), CONVERT(date, [INVOUTDATE], 105)) wk,
        CASE WHEN DATEPART(dw, CONVERT(datetime, ORDERDATE, 105)) = 7 THEN 1 ELSE 0 END IsSundayOrd,
        CASE WHEN DATEPART(dw, CONVERT(datetime, INVOUTDATE, 105)) = 7 THEN 1 ELSE 0 END IsSundayInv
    from S
)
select avg(cast(dd - case when dd>1 then (wk +  IsSundayOrd + IsSundayInv) else 0 end as float)) leadtime
from D
where CONVERT(date, ORDERDATE, 105) between '20170801' and '20170831' 
    AND CONVERT(date, INVOUTDATE, 105) IS NOT NULL

答案 1 :(得分:0)

我会尝试将您的日期转换为DATE instesad DATETIME我认为您过滤了太多行,因为&#39; 20170831&#39;是&#39; 2017-08-31 00:00:00&#39;而且你在{00} 00:00:00&#39;之间失去所有ORDERDATE和&#39; 59:59&#39; (对于&#39; 2017-08-31&#39;)

WHERE   ORDERTYPE <> 'Exchange Order' 
AND CONVERT(date, ORDERDATE, 105) between '20170801' and '20170831' 
AND CONVERT(date, INVOUTDATE, 105) IS NOT NULL

答案 2 :(得分:0)

在MtwStark的帮助下,我能够解决这个问题。 我修改了他的查询, 谢谢伙伴

;with
S AS (
SELECT DISTINCT DOCKETNO,
Case when CONVERT(datetime, ORDERDATE, 105) = CONVERT(datetime, INVOUTDATE, 105) THEN 0 else
Case when CONVERT(datetime, ORDERDATE, 105) + 1 = CONVERT(datetime, INVOUTDATE, 105) THEN 1 else
(DATEDIFF(dd, CONVERT(datetime, ORDERDATE, 105), CONVERT(datetime, INVOUTDATE, 105)))
-(DATEDIFF(wk, CONVERT(datetime, ORDERDATE, 105), CONVERT(datetime, INVOUTDATE, 105))*1)
-(CASE WHEN DATENAME(dw, CONVERT(datetime, ORDERDATE, 105)) = 'Sunday' THEN 1 ELSE 0 END)end end AS LEADTIME FROM DSORDERSTATUS
WHERE ORDERTYPE <> 'Exchange Order' 
AND CONVERT(datetime, ORDERDATE, 105) between '20170801' and '20170808' 
AND CONVERT(datetime, INVOUTDATE, 105) IS NOT NULL
),
D AS (
SELECT DOCKETNO, LEADTIME FROM S
)
SELECT AVG(CAST(LEADTIME AS FLOAT)) FROM D