2013-08-16 3 views
5

Скажем, у меня есть таблица, подобный следующему:ВЫБРАТЬ строк со вторым наивысшим значением в столбце

Item   Description   Time 
-----  -----------   ----- 
ItemA1  descript    08-16-2013 00:00:00 
ItemA2  descript    08-16-2013 00:00:00 
ItemA3  descript    08-16-2013 00:00:00 
. 
. 
ItemAN  descript    08-16-2013 00:00:00 

ItemB1  descript    08-13-2013 00:00:00 
ItemB2  descript    08-13-2013 00:00:00 
ItemB3  descript    08-13-2013 00:00:00 
. 
. 
ItemBN  descript    08-13-2013 00:00:00 
. 
. 
. 
ItemX1  descript    01-13-2012 00:00:00 
ItemX2  descript    01-13-2012 00:00:00 
ItemX3  descript    01-13-2012 00:00:00 
. 
. 
ItemXN  descript    01-13-2012 00:00:00 

Группы элементов добавляются периодически. Когда добавляется группа элементов, все они добавляются с тем же поле «Время». «Время» по существу служит уникальным индексом для этой группы элементов.

Я хочу выбрать группу элементов, имеющих второе по величине время. В этом примере мой запрос должен вытащить элементы «B». Я знаю, что могу сделать max (time), чтобы выбрать элементы «А», но я не знаю, как бы я занял второе место.

Мои столбцы «Время» хранятся как TIMESTAMP, если это что-то значит.

+0

Возможно, вы должны протестировать как решения MAX, так и LIMIT/ORDER BY, поскольку в зависимости от наличия индексов может быть недостаток производительности для LIMIT. http://stackoverflow.com/questions/426731/min-max-vs-order-by-and-limit –

+0

Возможный дубликат [Что такое простейший SQL-запрос, чтобы найти второе по величине значение?] (http: // stackoverflow .com/questions/32100/what-is-the-simpleest-sql-query-to-find-the-second-maximum-value) – heretolearn

ответ

13

Вы можете попробовать что-то вроде:

SELECT MAX(Time) 
FROM yourTable 
WHERE Time < (SELECT MAX(Time) FROM yourTable) 

SQLFiddle Demo

+0

Почему downvote? – DarkAjax

+0

+1 для симпатичной кнопки скрипта sql, но ваш запрос не дает элементов, а просто –

+0

@DarkAjax. Это решение не масштабируется вообще. Как бы вы тогда выбрали 3-й максимум? Или 4-й, 5-й, 6-й, n-й? – Pacerier

7

Один из подходов:

SELECT t.* 
FROM mytable t 
JOIN (SELECT l.time 
      FROM mytable l 
     GROUP BY l.time 
     ORDER BY l.time DESC 
     LIMIT 1,1 
    ) m 
    ON m.time = t.time 

Это используется вложенное (присваивается псевдоним м), чтобы вернуть второй «наибольший "значение времени. GROUP BY предоставляет нам отличный список, ORDER BY DESC ставит последние в первую очередь, а «трюк» - это LIMIT, который возвращает вторую строку. LIMIT (m, n) = (пропустите первые m строк, верните следующие n строк)

С этим значением времени мы можем присоединиться к исходной таблице, чтобы получить все строки, имеющие соответствующее значение времени.


Производительность будет повышена с индексом с ведущей колонки из time. (Я думаю, что MySQL должен быть в состоянии избежать операции «Использование файлового управления» и получить результат из запроса встроенного представления довольно быстро.)

Но, включая предикат в запросе встроенного просмотра, если вы «знаете», что второй последнее время никогда не будет больше определенное количество дней, не повредит производительности:

WHERE l.time > NOW() + INTERVAL -30 DAYS 

Но с этим добавило, то запрос не возвратит «второй последнюю» группы, если это time более 30 дней назад.

Подход к получению второго последнего (подход, приведенный в других ответах), может быть быстрее, особенно если нет индекса с ведущим столбцом time, но производительность лучше всего измерить путем фактического тестирования. Индекс с ведущим столбцом времени также ускорит подход MAX().)

Запрос, который я предоставил, может быть легко расширен, чтобы получить 4-е последнее, 42-е из последних и т. Д., Изменив предложение LIMIT ... LIMIT(3,1), LIMIT(41,1) и т. Д.

+0

+1 Лучший ответ. –

+0

* ПРИМЕЧАНИЕ. * В запросе в этом ответе используется специфичный для MySQL синтаксис LIMIT, который * не * поддерживается в большинстве (всех) других коммерческих базах данных. – spencer7593

+0

Синтаксис LIMIT в подзапросе не поддерживается для более ранних версий MySQL. – Manu

1
SELECT T1.ITEM 
FROM YOURTABLE T1 
WHERE T1.TIME = (SELECT MAX(T2.TIME) 
        FROM YOURTABLE T2 
        WHERE T2.TIME < (SELECT MAX(T3.TIME) 
             FROM YOURTABLE T3 
            ) 
       ) 
0

Что-то действительно просто, как это должно работать

select * from my-table where time = 
    (Select top 1 time 
    from (select top 2 time from my-table order by time desc) 
    order by time asc) 
+0

'TOP' - это синтаксис Microsoft SQL Server, не поддерживаемый MySQL. – spencer7593

+0

Вот почему вы должны пойти с соглашением MAX(), совместимым с ANSI ... –

4

Это должно дать вам второе самое большое время:

SELECT time FROM table GROUP BY time ORDER BY time DESC LIMIT 1,1 
1

Получить второй, третий, четвертый ...... Nth высокий используя следующий запрос:

SELECT MIN(value) from yourTable WHERE value IN(SELECT TOP N value FROM yourTable ORDER BY value DESC) 

Замените N номером i.e N = 2 для второго наивысшего значения, N = 3 для третьего наивысшего значения и так далее. Таким образом, для использования второго самого высокого значения:

SELECT MIN(value) from yourTable WHERE value IN(SELECT TOP 2 value FROM yourTable ORDER BY value DESC) 
0

Вот еще одно решение, которое я думаю, что должно работать для вашей проблемы:

CREATE TEMPORARY TABLE xHighest AS (SELECT DISTINCT Time FROM `my-table` ORDER BY Time DESC LIMIT 1,1); 

SELECT * FROM `my-table` JOIN xHighest ON (my-table.Time = xHighest.Time); 

Вы можете выбрать, если второй, третий, ... Наибольшее значение должно можно использовать, изменив первый параметр LIMIT.

0

MYSQL: предел раствор основания

Пример: записи 1, 2, 3, 4, 5. означает

ПРЕДЕЛ 2,1 он будет возвращать 3-е наибольшее число, так как LIMIT 1,1 возврата 2-е место и т. Д.

SELECT rc. rc_officer_id FROM recovery_complain_officer rc ORDER BY rc. rc_officer_id DESC LIMIT 2,1

Смежные вопросы