【问题标题】:Query not returning all results查询不返回所有结果
【发布时间】:2012-07-06 18:18:02
【问题描述】:

下面的查询应该返回 881 行,但只返回 744:

SELECT MIN(DateTime),AVG(ISNULL((Convert(decimal(10,3),SCR1_EXHAUST_GAS_TEMP)),0))
FROM jmusa_LOG1
GROUP BY DATEPART(HH,DateTime),DATEPART(DD,DateTime)
ORDER BY MIN(DateTime)

现在,如果我分别运行这两个查询,我分别得到 588 和 293,这等于我需要的 881:

SELECT MIN(DateTime),AVG(ISNULL((Convert(decimal(10,3),SCR1_EXHAUST_GAS_TEMP)),0))
FROM jmusa_LOG1
WHERE SCR1_EXHAUST_GAS_TEMP IS NULL
GROUP BY DATEPART(HH,DateTime),DATEPART(DD,DateTime)
ORDER BY MIN(DateTime)

上述语句的主要区别在于 WHERE 语句。

SELECT MIN(DateTime),AVG(ISNULL((Convert(decimal(10,3),SCR1_EXHAUST_GAS_TEMP)),0))
FROM jmusa_LOG1
WHERE SCR1_EXHAUST_GAS_TEMP IS NOT NULL
GROUP BY DATEPART(HH,DateTime),DATEPART(DD,DateTime)
ORDER BY MIN(DateTime)

这里也有相同的关键区别,请注意区别在于一个有 IS NULL,另一个 IS NOT NULL

现在有人知道为什么会这样吗?我可能的错误是什么导致第一次提到的查询没有返回所有 881 结果?

数据库管理器:SQL Server 2008 R2 和 SSMS 日期格式(如有必要):YYYY-MM-DD HH:MM:SS.000

【问题讨论】:

  • 您的两个单独的查询是否有任何重复的条目 GROUP BY 条目?如果是这样,则它们在您的单独查询中被重复计算,但在单个查询中合并为单个计算。
  • 不,我仔细检查并确保它们不重复

标签: sql sql-server select group-by average


【解决方案1】:

您有以下组合:

DATEPART(HH,DateTime),DATEPART(DD,DateTime)

其中 DATEPART(HH,DateTime),DATEPART(DD,DateTime) 采用 NULL 值和非 NULL 值。

换句话说,由两个独立查询定义的组重叠。

【讨论】:

  • DateTime 列中的每一行都是唯一值,没有任何值是 NULL。也许我理解错了?
  • 不,问题是 group by。您正在为三个查询中的每一小时和每一天创建一个单独的组。当您将其一分为二时,两个查询中都会包含几个小时。
  • @GordonLinoff - +1,假设您的意思是 SCR1_EXHAUST_GAS_TEMP 的 NULL 和 NOT NULL 值,对吧?
  • @GordonLinoff 就是这样,每个单独的查询都提供独特的结果,这意味着当它们组合时应该提供 881 个而不是 744 个结果
  • 当然结果是独一无二的。每一行可能有不同的最小值。输入小时和天,您会发现这些是重复的。
【解决方案2】:

您确定 HH、DD 和 NULL(SCR1_EXHAUST) 的组合是唯一的吗?

如果两行,即使它们具有不同的 DateTimes,但设法具有相同的 HH 和 DD,并且一个具有 NULL SCR1_EXHAUST_GAS_TEMP 而另一个具有不同的空相同,则 GROUP BY 会将它们合并为一行。

在这种情况下,您还需要在 ISNULL(SCR1_EXHAUST_GAS_TEMP) 上进行分组。

SELECT MIN(DateTime),AVG(ISNULL((Convert(decimal(10,3),SCR1_EXHAUST_GAS_TEMP)),0))
FROM jmusa_LOG1
GROUP BY ISNULL(SCR1_EXHAUST_GAS_TEMP, 0)=0, DATEPART(HH,DateTime),DATEPART(DD,DateTime)
ORDER BY MIN(DateTime)

...否则,也许 744 行 确实是您所需要的。

现在,如果您想查看所有日期,但其中一些日期有垃圾值,那么您需要:

  • 通过提取 YYYY、MM、DD、HH 的不同值来准备第一组,这将是您的“日历”
  • 准备第二组,您将在其中平均非空值 temp,按 YYYY、MM、DD 和 HH 分组
  • LEFT JOIN 日历与数据,在 YYYY、MM、DD 和 HH 上加入并获得这些数据,加上 TEMP,并按 y、m、d、h 排序。

这会给你类似的东西,

Year Mo Da HH Temp
2012 07 07 00  750
2012 07 07 01  633
2012 07 07 02  NULL    <-- from 02:00 to 02:59 we only have junk!
2012 07 07 03  660     (actually, when going from summer time to winter time...)
2012 07 07 04  680

【讨论】:

  • 我尝试了您刚才所说的按 ISNULL(SCR_EXHAUST_GAS_TEMP) 分组,但随后按小时分组消失了。
  • 这意味着你确实有相同的 DD/HH 和不同的 gastemp 空值,不是吗?所以也许你真的需要 744 行。如果在同一个小时组中,您希望合并零温度和非零温度读数,那么当然这两个组必须重叠,您将获得少于 881 行。尽管 DateTimes 是唯一的,但小时却不是。
  • 嗯,就是这样。如果 6 月 6 日晚上 8 点的列具有空值和非空值,则应以跳过空值并平均非空值的方式返回该小时的平均值,所以基本上我希望一天中的所有时间都不考虑要平均的值而返回。但是某些日子不会被退回,例如从 6 月 8 日到 16 日根本不会被退回,这让我很担心
  • 但这就是 Gordon Linoff 所说的——您忽略了两行之一,即 NULL 行。所以总和不能再给出 881。你只考虑 NULL 行,如果它们是那一天和那个小时的唯一行。有时它们并不孤单,它们会从 881 中删除,产生 744。
  • 好吧,有些数据可能是相同的,我不明白为什么应该删除这些数据。如果我的客户单位吐出这个数字,而它恰好与一个月前发生的数字相同,为什么它们应该“相交”并归为 1?
【解决方案3】:

以下查询应向您显示 2 组中重叠的行:

SELECT DATEPART(HH,DateTime),DATEPART(DD,DateTime)
FROM jmusa_LOG1
WHERE SCR1_EXHAUST_GAS_TEMP IS NULL
GROUP BY DATEPART(HH,DateTime),DATEPART(DD,DateTime)

intersect

SELECT DATEPART(HH,DateTime),DATEPART(DD,DateTime)
FROM jmusa_LOG1
WHERE SCR1_EXHAUST_GAS_TEMP IS NOT NULL
GROUP BY DATEPART(HH,DateTime),DATEPART(DD,DateTime)

【讨论】:

  • 现在你让我知道了一些事情。无论交叉点如何,我如何获得结果。基本上忘记了交叉路口,只发回所有东西?
  • 这里的重点是:为什么你认为你应该有 881 行?你说:它是集合的总和。但是如果集合重叠......那么并集的基数不是基数的总和
  • 我的客户有这个日志文件,他每分钟都有数据。他想把那一天和那一小时平均下来。现在,一些被平均的数据点将是 NULL,因为这些是“垃圾”值,其他的将是非 NULL
  • 那么,恕我直言,您应该通过 where 子句排除那些垃圾行
  • 如果你想要“所有日期”,我已经编辑了我的答案 - 我认为应该可以。
猜你喜欢
  • 1970-01-01
  • 2015-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-05
  • 1970-01-01
相关资源
最近更新 更多