【问题标题】:How to select the first row for each group (ordering by datetime)?如何为每个组选择第一行(按日期时间排序)?
【发布时间】:2013-02-16 20:42:57
【问题描述】:

如何为 MySQL 中的每个组选择第一行(按日期时间排序)?

我试过了,我做到了:

SELECT *
FROM `cats`
WHERE `war_id` = 0 
AND `eyes_color` = 'green' 
AND `id` IN
    (SELECT `id` FROM
        (SELECT * FROM `cats` ORDER BY `date_last_fought` DESC) AS t
    GROUP BY `war_id`, `n_of_medals`)

有点效果,但我不确定它是否是有史以来最好的。

你认为我可以简化这个吗?

【问题讨论】:

  • 这实际上似乎是最好的选择。把它变成同一张桌子上的连接没有多大意义。但是,您应该将SELECT `id` 放在最里面的查询中,并将SELECT * 放在任何包装查询中。

标签: mysql group-by subquery


【解决方案1】:

我试着简化成这个...

SELECT * FROM `cats`
inner join (select * from cats 
        WHERE `warid` = 1 AND `color` = 'green' 
        order by orderDate desc) a 
        on (cats.id=a.id)
group by cats.warId;


你可以在这里看到http://sqlfiddle.com/#!2/55f5b/5
但我不确定它是否比您的查询更好,...阅读并从 EXPLAIN 中采取行动仍然成为我的作业:D

ID  SELECT_TYPE TABLE      TYPE    POSSIBLE_KEYS    KEY   KEY_LEN   REF    ROWS EXTRA
1   PRIMARY     <derived2> ALL     (null)          (null) (null)    (null)   2  Using temporary; Using filesort
1   PRIMARY     cats       eq_ref  PRIMARY         PRIMARY  4       a.id     1  
2   DERIVED     cats       ALL     (null)          (null) (null)    (null)   6  Using filesort

添加索引会更快

【讨论】:

  • 有什么办法可以去掉子查询,仍然有一个查询?
  • @CarlosP 没有任何可靠的方法。如果你小心的话,有一些索引技巧几乎总能奏效。
  • 你必须使用两个*吗?此查询将结合两个数据集。在这种情况下,你只需要在内部连接查询中获取 id。
【解决方案2】:

这是我的解决方案:

SELECT * FROM `cats` c
JOIN (
    SELECT `war_id`, `n_of_medals`, MAX(`date_last_fought`) date_last_fought
    FROM `cats` 
    WHERE `war_id` = 0 
    AND `eyes_color` = 'green' 
    GROUP BY `war_id`, `n_of_medals` 
) c_summary ON c_summary.war_id = c.war_id
AND c_summary.n_of_medals = c.n_of_medals 
AND c_summary.date_last_fought = c.date_last_fought
ORDER BY c.`date_last_fought` DESC;

http://sqlfiddle.com/#!2/05bcb/2

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-09
    • 1970-01-01
    • 1970-01-01
    • 2016-12-16
    • 2022-01-18
    • 2019-07-01
    • 2015-07-24
    • 1970-01-01
    相关资源
    最近更新 更多