MySQL: как получить n последних строк различного типа - PullRequest
4 голосов
/ 04 июня 2009

Говоря так просто, я могу иметь следующую структуру таблицы:

Date | Type | Title

Скажите Type - это значение в диапазоне 1-10, у меня в таблице тысячи записей, и я хочу 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, который будет применяться после и ORDER BY предложения.

Все в MySQL 4.

Ответы [ 6 ]

7 голосов
/ 04 июня 2009

Я что-то упустил? Простое решение выглядит следующим образом:

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

И это должно быть очень быстро.

2 голосов
/ 04 июня 2009

Не проверял на 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.

1 голос
/ 04 июня 2009

Это хороший пример для оператора объединения и вложенных выборок.

Что-то вроде:

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 поддерживаются как вложенные select, так и объединения, согласно справочному руководству. (Я добавил предложение as во вложенный оператор from на основе документации mysql.)

1 голос
/ 04 июня 2009

Предполагая, что производительность запросов несколько важна, и вы застряли с 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 или другой базой данных, были бы более подходящие способы решения этой проблемы.

0 голосов
/ 02 сентября 2014

Я знаю, что было немного поздно, но у меня возникла та же проблема, и я понял, как: так что я пишу.

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 отсортированы по столбцу Date. В этой таблице последняя запись для конкретный тип выше всех других записей того же типа. Эта возвращаемая таблица переименована в t.

  2. Теперь операция GROUP BY выполняется для этой таблицы на основе столбца Тип. Результатом будет первая найденная строка каждого типа.

  3. Теперь добавьте условие LIMIT к получить первые 5 строк.

0 голосов
/ 29 июля 2013

Попробуйте это

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. Предполагается, что поле даты уникально. Если у вас есть первичный ключ, отличный от даты, используйте его в запросе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...