如何在一个选择中获得每个类别的最新2项(使用mysql)

时间:2009-07-07 12:20:43

标签: sql mysql

我的数据如下所示:

id|category|insertdate|title....
--------------------------------
1|1|123|test 1
2|1|124|test 2
3|1|125|test 3
4|2|102|test 4
5|2|103|test 5
6|2|104|test 6

我尝试完成的是获取每个类别的最新2个条目(按插入日期DESC的顺序),因此结果应为:

id|....
----
3|....
2|....
6|....
5|....

使用group by获取最新信息很简单,但如何在不启动多个查询的情况下获取最新信息?

感谢您的帮助;-)
S上。

5 个答案:

答案 0 :(得分:7)

这在SQL中是一个棘手的问题,最好通过引导您阅读一篇涵盖该问题的优秀深度文章来解答:How to select the first/least/max row per group in SQL。它涵盖了MySQL特定的方法,以及通用方法。

答案 1 :(得分:3)

在这里,你好友!

SET @counter = 0;
SET @category = '';

SELECT
    *
FROM
(
    SELECT
        @counter := IF(data.category = @category, @counter+1, 0) AS counter,
        @category := data.category,
        data.*
    FROM
    (
        SELECT
            *
        FROM test
        ORDER BY category, date DESC
    ) data
) data
HAVING counter < 2

答案 2 :(得分:0)

您无法在一个SELECT语句中执行此类查询,但您可以将其包装在一个存储过程中,该过程通过将子查询的结果添加到每个类别的临时表中来返回一个数据集,然后返回临时表的内容。

伪代码:

Create a temp table
For each distinct category,
  Add the last two records to the temp table
Return the temp table

您最终将获得所需的数据集,并且从您的应用程序的角度来看,只进行了一次查询。

答案 3 :(得分:0)

另一种方法是使用group_concat获取有序列表。如果您拥有大量数据,那么这不会有任何用处。

select group_concat(id order by insertdate desc separator ','), category from tablename group by category

或使用子选择(在mysql上)

select category,
    (select id from test as test1 where test1.category = test.category order by insertdate desc limit 0,1) as recent1,
    (select id from test as test1 where test1.category = test.category order by insertdate desc limit 1,1) as recent2
from test
group by category;

我知道第二个选项在技术上并不是一个选择,因为有子查询但是这是我能看到的唯一方法。

答案 4 :(得分:0)

SELECT * 
FROM category AS c1
WHERE (
    SELECT COUNT(c2.id)
    FROM category AS c2
    WHERE c2.id = c1.id AND c2.insertdate > c1.insertdate
) < 2