【问题标题】:SQL Select record with MAX non zero value If exists otherwise select record with zero valueSQL 选择具有 MAX 非零值的记录 如果存在,否则选择具有零值的记录
【发布时间】:2015-07-08 17:51:57
【问题描述】:

我想做的是从我的表中为给定日期范围内的每个唯一时间戳选择一条记录。如果同一时间戳存在多个记录,我想获得最大的非零记录,或者如果只返回零值记录,我只想返回那些零值记录之一。 我一直在使用“几乎”的查询是

select timestamp, MAX(value) FROM myTable WHERE *conditions*... group by [timestamp] Order By [timestamp] ASC;

在返回的记录是零和负数之前它显然工作得很好,在这种情况下它返回零记录,因为它大于负记录。在这种情况下,我想返回负值记录之一,而不是零记录。如果我尝试通过将 where 语句更改为

来解决这个问题
WHERE [Value] <> 0

如果只返回零值记录,我什么也得不到。我的优先级是每个时间戳返回一个最大的非零值记录,但如果只存在零值记录,则只返回其中一个,如果时间戳只存在空记录,我希望返回单个空记录。

【问题讨论】:

  • 如果您只希望返回 1 条记录...为什么要按 timstamp 订购?由于order by value desc,只有select timestamp, value from table where *conditions* order by value desc limit 1 最大值将是第一条记录,并且限制1 将确保只有1 条记录返回。无论是 0 还是 1 值。现在,如果由于“条件”而根本没有记录,那就是另一回事了...但是您说记录正在恢复...正如您现在所拥有的那样,您返回的最大值可能没有关系到它旁边列出的时间戳...
  • 我只想要每个唯一时间戳 1 条记录,但我的查询可能会返回数百条唯一时间戳记录。例如,当我从每日数据表中查询 90 天时,我希望收到 90 条记录。

标签: mysql


【解决方案1】:

我会按照您描述的方式选择最大的非零值:

SELECT timestamp, MAX(valueCol) AS maxValue
FROM myTable
WHERE valueCol <> 0
GROUP BY timestamp;

然后,您可以使用外连接获取所有时间戳,并使用COALESCE() 函数将未返回的值替换为 0:

SELECT m.timestamp, COALESCE(t.maxValue, 0) AS maxValue
FROM myTable m
LEFT JOIN(
   SELECT timestamp, MAX(valueCol) AS maxValue
   FROM myTable
   WHERE valueCol <> 0
   GROUP BY timestamp) t ON t.timestamp = m.timestamp;

编辑:根据您的 cmets 和对您问题的编辑,您可以通过以下方式分解问题。我写了一个查询(如上所示)来获取每个时间戳的最大非零值。我还可以编写一个查询来获取最大/最小时间戳为 0 的时间戳,如下所示:

SELECT id, 0 AS MaxVal
FROM myTable
GROUP BY id
HAVING MAX(valueCol) = 0 AND MIN(valueCol) = 0;

剩余组的值为 null。要获得这些,我可以执行与前面示例相同的外部连接,但省略 COALESCE() 函数,以便空值保持原样:

SELECT DISTINCT m.id, t.maxVal
FROM myTable m
LEFT JOIN(
  SELECT id, MAX(valueCol) AS maxVal
  FROM myTable
  WHERE valueCol <> 0
  GROUP BY id
  UNION ALL
  SELECT id, 0 AS maxVal
  FROM myTable
  GROUP BY id
  HAVING MIN(valueCol) = 0 AND MAX(valueCol) = 0) t ON t.id = m.id;

我添加了 DISTINCT 关键字来返回唯一的 id/maxValue 对,否则会返回多行,因为 id 在同一个表中出现多次。

我在SQL Fiddle 中对此进行了测试,效果很好。

【讨论】:

  • 我已经尝试过了,但也许我需要更具体地回答我的问题,实际上有 3 种类型的记录,非零、零和空。如果它们存在,我想先返回非零,然后如果非零不存在,我想返回零记录,然后如果零记录不存在但空记录存在,我想返回空值。在您的回答中,我相信空记录也会归零。
  • 我明白了。这是可能的,今天工作互联网参差不齐,所以我会尽可能编辑。
  • @AaronKruger 请参阅编辑。我希望这是你所期待的。
【解决方案2】:

试一试,将@ValueCol 更改为 1、0,null 可以正常工作。

DECLARE @ValueCol INT 
SET @ValueCol = Null

Select CASE WHEN MAX( CASE WHEN @ValueCol IS NULL THEN 1 ELSE 0 END) = 0  THEN MAX(@ValueCol) END

这样你的 SQL 就会像原来的帖子那样。

select 
timestamp
, CASE WHEN MAX( CASE WHEN value IS NULL THEN 1 ELSE 0 END) = 0  THEN MAX(value) END
FROM myTable 
WHERE *conditions*... 
group by [timestamp] 
Order By [timestamp] ASC;

【讨论】:

  • 谢谢,这正是我所需要的,而且非常简短!我在我们的数据库上对其进行了测试,它在处理非零、零和空时间戳记录方面表现出色。我会投票给你的答案,但我还没有足够的代表点数。一旦我这样做,我会回来投票。
  • 任何时候,SQL 对我来说都是一个有趣的游戏,我喜欢在不编写自己的代码时查看所有这些问题。像你一样,我以前不得不处理这种情况,这是我能想到的最优雅的事情。很高兴它对你有用!
猜你喜欢
  • 2012-01-13
  • 1970-01-01
  • 1970-01-01
  • 2019-01-28
  • 1970-01-01
  • 2021-03-22
  • 2012-05-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多