选择3个最新记录,其中一列的值不同

时间:2009-05-29 05:20:58

标签: mysql group-by sql-order-by

我有下表:

    id       time      text      otheridentifier
    -------------------------------------------
    1        6         apple     4
    2        7         orange    4
    3        8         banana    3
    4        9         pear      3
    5        10        grape     2

我想要做的是选择3个最近的记录(按时间desc),其otheridentifier是不同的。所以在这种情况下,结果将是id:5,4和2。

id = 3将被跳过,因为最近的记录具有相同的otheridentifier字段。

这是我试图做的事情:

SELECT * FROM `table` GROUP BY (`otheridentifier`) ORDER BY `time` DESC LIMIT 3

但是,我最终得到id = 5, 3 1 的行,而不是预期的5,4,2行。

有人可以告诉我为什么这个查询不会返回我的预期吗?我尝试将ORDER BY更改为ASC,但这只是将返回的行重新排列为1,3,5。

8 个答案:

答案 0 :(得分:34)

它没有返回您的期望,因为在排序之前发生了分组,这反映在SQL语句中子句的位置。不幸的是,你必须得到更好的方法来获得你想要的行。试试这个:

SELECT *
FROM `table`
WHERE `id` = (
    SELECT `id`
    FROM `table` as `alt`
    WHERE `alt`.`otheridentifier` = `table`.`otheridentifier`
    ORDER BY `time` DESC
    LIMIT 1
)
ORDER BY `time` DESC
LIMIT 3

答案 1 :(得分:18)

您可以自己加入表格来过滤每个otheridentifier的最后一个条目,然后取出前3行:

SELECT last.*
FROM `table` last
LEFT JOIN `table` prev 
    ON prev.`otheridentifier` = last.`otheridentifier`
    AND prev.`time` < last.`time`
WHERE prev.`id` is null
ORDER BY last.`time` DESC 
LIMIT 3

答案 2 :(得分:4)

我有类似的要求,但我有更高级的选择标准。使用其他一些答案我无法得到我需要的东西,但我发现你仍然可以在这之后进行GROUP BY和ORDER BY:

SELECT t.* FROM (SELECT * FROM table ORDER BY time DESC) t 
GROUP BY t.otheridentifier

答案 3 :(得分:2)

SELECT * FROM table t1 
WHERE t1.time = 
    (SELECT MAX(time) FROM table t2 
     WHERE t2.otheridentifier = t1.otheridentifier)

答案 4 :(得分:2)

Andomar's answer可能是最好的,因为它不使用子查询。

另一种方法:

select *
from   `table` t1
where  t1.`time` in (
                    select   max(s2.`time`)
                    from     `table` t2
                    group by t2.otheridentifier
                    )

答案 5 :(得分:2)

您可以使用此查询获得正确答案:

SELECT * FROM 
      (SELECT * FROM `table` order by time DESC)
          t group by otheridentifier

答案 6 :(得分:1)

怎么样

SELECT *, max(time) FROM `table`  group by otheridentifier

答案 7 :(得分:0)

这也是:

SELECT * FROM
OrigTable T INNER JOIN 
( 
SELECT otheridentifier,max(time) AS duration
FROM T
GROUP BY otheridentifier) S
ON S.duration = T.time AND S.otheridentifier = T.otheridentifier.