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

Ada*_*rle 9 mysql database group-by

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

我试过了:

SELECT title, timestamp, category_id
FROM blogs 
WHERE timestamp IN (
  SELECT MAX(timestamp) 
  FROM blogs 
  GROUP BY category_id
)
Run Code Online (Sandbox Code Playgroud)

但由于时间戳是不是唯一的,它可以,比方说,拉一个额外一行CATEGORY_ID = 1具有相同的时间戳与CATEGORY_ID = 2行是在内部select语句选择.

spe*_*593 9

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

SELECT b.title
     , MAX(b.timestamp)
     , b.category_id
  FROM blogs b
 GROUP BY b.category_id
Run Code Online (Sandbox Code Playgroud)

如果在具有相同最新"时间戳"的类别中碰巧有多个"标题",则只返回该类别的一行,因此每个类别只返回一个"标题".


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

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

SELECT category_id, MAX(timestamp) AS timestamp
  FROM blogs
 GROUP BY category_id
Run Code Online (Sandbox Code Playgroud)

下一步是将其加入blogs,以获得相关的"标题"(s)

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 
Run Code Online (Sandbox Code Playgroud)

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

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


简单地向该查询添加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
Run Code Online (Sandbox Code Playgroud)

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

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