MySQL:如何获取n个不同类型的最新行

时间:2009-06-04 13:34:17

标签: sql mysql

尽我所能,我有以下表格结构:

Date | Type | Title

Say Type是1-10范围内的值,表中有1,000条记录,我想要5条最新的唯一类型记录。所以结果会是这样的:

             Date | Type | Title
2009-06-04 14:32:00 | 4 | Zeppo
2009-06-04 14:31:00 | 2 | Groucho
2009-06-04 14:30:00 | 8 | Harpo
2009-06-04 14:29:00 | 5 | Gummo
2009-06-04 14:28:00 | 3 | Chico

似乎我要求DISTINCT仅适用于Type列,或者我想要一个GROUP BY,它将在 {{1}之后应用条款。

全部在MySQL 4中。

6 个答案:

答案 0 :(得分:7)

我错过了什么吗?简单的解决方案似乎是:

SELECT  MAX(date) AS max_date, type, title
FROM    table
GROUP BY
        type  
ORDER BY
        max_date DESC
LIMIT 5

它应该非常快。

答案 1 :(得分:2)

没有为MySQL 4进行测试,但在MySQL 5中可以轻松完成。

您需要在表格中使用某种PRIMARY KEY才能实现此目的。

SELECT  l.*
FROM    (
        SELECT  type,
                COALESCE(
                (
                SELECT  id
                FROM    mytable li
                WHERE   li.type= dlo.type
                ORDER BY
                        li.type DESC, li.date DESC, li.id DESC
                LIMIT 4, 1
                ), CAST(0xFFFFFFFF AS DECIMAL)) AS mid
                COALESCE(
                (
                SELECT  date
                FROM    mytable li
                WHERE   li.type= dlo.type
                ORDER BY
                        li.type DESC, li.date DESC, li.id DESC
                LIMIT 4, 1
                ), '9999-31-12') AS mdate
        FROM    (
                SELECT  DISTINCT type
                FROM    t_mytable dl
                ) dlo
        ) lo, t_mytable l
WHERE   l.type >= lo.type
        AND l.type  <= lo.type
        AND (l.date, l.id) >= (lo.mdate, lo.mid)

有关其工作原理的详细信息,请参阅我的博客中的此条目:

如果您无法添加PRIMARY KEY来实施此解决方案,您可以尝试使用效率较低的系统变量:

SELECT  l.*
FROM    (
        SELECT  @lim := 5,
                @cg := -1
        ) vars,
        mytable l
WHERE   CASE WHEN @cg <> type THEN @r := @lim ELSE 1 END > 0
        AND (@r := @r - 1) >= 0
        AND (@cg := type) IS NOT NULL
ORDER BY
        type DESC, date DESC

这里描述:

<强>更新

如果您不想为每种类型选择5条记录(这会在结果集中提供5 x number of types条记录),而是希望选择5具有不同类型的最新记录(这将在结果集中提供5条记录),使用此查询:

SELECT  date, type, title
FROM    mytable m
WHERE   NOT EXISTS
        (
        SELECT  1
        FROM    mytable mi
        WHERE   mi.date > m.date
                AND mi.type = m.type
        )
ORDER BY
        date DESC
LIMIT 5

如果您有很多类型,只要您在GROUP BY上有索引,这将比使用date更有效。

答案 2 :(得分:1)

假设查询性能有点重要并且你遇到了MySQL 4,我会选择这样的东西:

SELECT Date, Type, Title
FROM (
    SELECT Date, Type, Title
    FROM Table
    WHERE Type = 1
    ORDER BY Date
    LIMIT 1

    UNION ALL

    SELECT Date, Type, Title
    FROM Table
    WHERE Type = 2
    ORDER BY Date
    LIMIT 1

    ...
) x
ORDER BY Date
LIMIT 5

它不漂亮,但应该快速完成工作。如果您经常向类型列添加新值,则可能不适合您,因为它需要定期修改查询。

我认为派生表是在4.1中添加的,所以你需要在4系列中至少达到那么高。如果您使用的是版本5或其他数据库,那么可以采用更好的方法来解决这个问题。

答案 3 :(得分:1)

这似乎是union语句和嵌套选择的好例子。

有些事情:

select t.date, t.type, t.title from (Select top 5 table.Date, table.Type, table.Title from table where type = 1 order by table.date desc) as t

union

select t2.date, t2.type, t2.title from (Select top 5 table.Date, table.Type, table.Title from table where type = 2 order by table.date desc) as t2

[...]

select t10.date, t10.type, t10.title from (Select top 5 table.Date, table.Type, table.Title from table where type = 10 order by table.date desc) as t10

order by type, date

不幸的是,我只有sql server 2008来测试这个,所以ymmv;但这是非常基本的东西,它应该工作,因为根据参考指南,mysql 4.0支持嵌套选择和联合。 (我已经根据mysql文档将as子句添加到嵌套的from语句中。)

答案 4 :(得分:0)

试试这个

select
    T.*
from
        (select
            max(date) dt,
            Type
        from
            table
        group by type
        order by dt desc
        limit 5) subQuery 
        inner join table T on T.date = subQuery.dt and T.Type = subQuery.Type

我只在MySQL 5上尝试过。这假设日期字段是唯一的。如果您拥有日期以外的主键,请在查询中使用该键。

答案 5 :(得分:0)

我知道它有点晚了,但遇到了同样的问题,并弄明白了:所以我发布了。

SELECT t.Date, t.Type, t.Title
FROM (SELECT Date, Type, Title FROM table ORDER BY Date DESC) AS t
GROUP BY t.Type LIMIT 5;

我认为这不是一个更简单的解决方案。

<强> 解释

  1. 首先执行内部SELECT。这将返回一个表 行,DESC按日期列排序。在此表中,最新条目为 特定类型是相同类型的所有其他条目。 此返回表重命名为t。

  2. 现在,基于Type列对此表执行GROUP BY操作。 结果将是每种类型遇到的第一行。

  3. 现在添加一个LIMIT条件 得到前5行。