【问题标题】:SQL - AVG Output is incorrectSQL - AVG 输出不正确
【发布时间】:2018-03-10 01:52:00
【问题描述】:

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

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

为了解决上述查询,我​​使用下面的相同查询提取数据,当我手动计算提前期并取平均值时,它是正确的。 不知道问题出在哪里?有人可以告诉我我的查询是否有问题。 请点击链接参考样本数据Link

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

【问题讨论】:

  • 输出不正确怎么办?请添加示例数据、预期输出和实际输出。
  • 数据文件很大。预期的输出是 1.3078,但我得到的是 1.4328。此外,当我使用相同的查询手动计算时,我得到了正确的输出
  • 你能创建一个同样问题的小数据样本吗?
  • 您正在使用select distinct 提取数据。您正在取所有数据的平均值。两个数据集不等价。
  • 在你的数据中还有DISTINCT子句,删除它并生成一个新的xlsx,请使用这个查询SELECT DISTINCT ORDERDATE, INVOUTDATE FROM DSORDERSTATUS WHERE ORDERTYPE &lt;&gt; 'Exchange Order' AND CONVERT(datetime, ORDERDATE, 105) between '20170801' and '20170808' AND CONVERT(datetime, INVOUTDATE, 105) IS NOT NULL

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


【解决方案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

【讨论】:

  • 这是 sql-server
  • 那么为什么我在执行上述代码时会出错
  • 好的..我已经离开办公室了。从移动访问此。我明天早上试试。感谢您的帮助
  • 我收到转换失败错误,请看错误截图。 Error
  • 亲爱的 Mtwstark,根据您的查询,即使我更改日期,我也会得到相同的输出,即 1.24。但最后在您的帮助下,我明白了一些事情,并且我修改了您的查询,并且在每种情况下都使用该查询,我得到了正确的输出。谢谢你。你太棒了
【解决方案2】:

我会尝试将您的日期转换为 DATETIMEDATE instesad 我认为您过滤的行太多,因为 '20170831' 是 '2017-08-31 00:00:00' 并且您将失去所有 @ 987654323@ 在 '00:00:00' 和 '23:59:59' 之间(对于 '2017-08-31')

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

【讨论】:

  • 感谢宝贵的回复,但我仍然得到相同的输出
  • 您是否尝试在查询中也使用DATE 而不是DATETIME
  • 我按照您的建议进行了尝试,但不理解“查询内部”??你的意思是我应该用日期替换所有的日期时间吗?如果是,那么是的,我尝试并得到了错误
【解决方案3】:

在 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

【讨论】:

  • 你能解释一下THEN 0 ELSE 0 END对于INVOUTDATE的星期日的含义吗?
  • 我猜这只是一个无用的。很抱歉我已将其删除。
  • 尤里卡!我终于明白问题出在哪里了!您有数千行 [DOCKETNO] = NULL 但不同的是 [ORDERDATE][INVOUTDATE] 所以,问题是:如何处理这个?它们的顺序相同吗?按日期分组是否正确?
  • 是的,将它们分组也可以提取唯一值,但您共享的 qry 首先是提取唯一值,然后是计算提前期,然后是计算该提前期的平均值,但是每次它给我相同的输出,即使我更改日期并且输出是 1.24 所以不是首先我用不同的案卷编号计算提前期,然后我从 S 表中选择提前期列,然后使用计算平均来自 D 的交货时间。谢谢,这将在未来帮助我。你只是gr8。只有你的逻辑才有可能
  • 我很高兴能帮上忙 :)
猜你喜欢
  • 2021-03-05
  • 1970-01-01
  • 1970-01-01
  • 2013-08-31
  • 1970-01-01
  • 2020-12-12
  • 2013-02-25
  • 1970-01-01
相关资源
最近更新 更多