选择每个类别中具有最大时间戳的行

时间:2012-08-02 17:53:28

标签: mysql database group-by

我有一个MySQL数据库(博客),它有id,title,timestamp和category_id列名。如何从每个具有最新时间戳的类别中选择一行? 如果我有3行属于类别1,2,1,那么我将返回两行,其中“1”中类别的最高时间戳作为第一行,而行类别“2”作为第二行。

我试过了:

SELECT title, timestamp, category_id
FROM blogs 
WHERE timestamp IN (
  SELECT MAX(timestamp) 
  FROM blogs 
  GROUP BY category_id
)

但由于时间戳不是唯一的,因此可以拉入一个额外的行,其中category_id = 1与内部select语句中选择的category_id = 2的行具有相同的时间戳。

2 个答案:

答案 0 :(得分:9)

对于MySQL,此查询将返回您指定的结果集:

SELECT b.title
     , MAX(b.timestamp)
     , b.category_id
  FROM blogs b
 GROUP BY b.category_id

如果在具有相同最新“时间戳”的类别中碰巧有多个“标题”,则只返回该类别的一行,因此您将只获得一个“标题“为每个类别返回。


注意:由于处理SELECT列表中未出现在GROUP BY中的非聚合,其他DBMS系统将使用上述查询引发异常(错误)。

您的查询非常接近。您已经有内部查询返回每个类别的“最新”时间戳。下一步是返回category_id以及最新的时间戳。

SELECT category_id, MAX(timestamp) AS timestamp
  FROM blogs
 GROUP BY category_id

下一步是将其加入blogs,以获取相关的“标题”

SELECT b.title
     , b.timestamp
     , b.category_id
  FROM (SELECT category_id, MAX(timestamp) AS timestamp
          FROM blogs 
         GROUP BY category_id
       ) l
  JOIN blogs b
    ON b.category_id = l.category_id AND b.timestamp = l.timestamp 

注意:如果某个类别有多个“最新”行(时间戳值匹配),则此查询将返回这两个行。

如果这是一个问题,可以修改(或以不同的方式编写)查询,以防止类别的两行可能。


简单地向该查询添加GROUP BY子句将起作用(仅在MySQL中,而不是在其他DBMS中)

SELECT b.title
     , b.timestamp
     , b.category_id
  FROM (SELECT category_id, MAX(timestamp) AS timestamp
          FROM blogs 
         GROUP BY category_id
       ) l
  JOIN blogs b
    ON b.category_id = l.category_id AND b.timestamp = l.timestamp
 GROUP BY b.timestamp, b.category_id

(对于其他DBMS,您可以修改SELECT列表,将b.title替换为MAX(b.title) AS title。当您从行返回单个列时,这将起作用。

如果要按特定顺序返回行,请添加ORDER BY子句。


答案 1 :(得分:0)

您也可以尝试这种方式。当我在MYSQL 5.6中尝试时,对我有用。它返回两个类别,其中包含category_id的最高时间戳和升序。

  

选择标题        ,时间戳        ,category_id FROM blogs WHERE时间戳记(从按类别列出的博客组中选择最大值(时间戳))group by   time_amp,category_id order by category_id asc;