Вопрос:

Выберите 3 самые последние записи, в которых значения одного столбца различны

mysql group-by sql-order-by

35891 просмотра

8 ответа

14409 Репутация автора

У меня есть следующая таблица:

    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 самые последние записи (по времени), чьи записи 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.

Автор: atp Источник Размещён: 29.05.2009 05:20

Ответы (8)


34 плюса

107410 Репутация автора

Решение

Он не возвращает того, что вы ожидаете, потому что группировка происходит перед упорядочением, что отражается положением предложений в операторе 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
Автор: chaos Размещён: 29.05.2009 05:24

2 плюса

27135 Репутация автора

SELECT * FROM table t1 
WHERE t1.time = 
    (SELECT MAX(time) FROM table t2 
     WHERE t2.otheridentifier = t1.otheridentifier)
Автор: Rytmis Размещён: 29.05.2009 05:31

18 плюса

200349 Репутация автора

Вы можете присоединиться к самой таблице, чтобы отфильтровать последнюю запись 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
Автор: Andomar Размещён: 29.05.2009 05:31

2 плюса

118532 Репутация автора

Ответ Andomar, вероятно, лучший в том, что он не использует подзапрос.

Альтернативный подход:

select *
from   `table` t1
where  t1.`time` in (
                    select   max(s2.`time`)
                    from     `table` t2
                    group by t2.otheridentifier
                    )
Автор: bernie Размещён: 29.05.2009 05:43

1 плюс

164 Репутация автора

что о

SELECT *, max(time) FROM `table`  group by otheridentifier
Автор: mbo Размещён: 29.02.2012 06:19

4 плюса

6743 Репутация автора

У меня было похожее требование, но у меня были более продвинутые критерии отбора. Используя некоторые другие ответы, я не смог получить именно то, что мне было нужно, но я обнаружил, что вы все еще можете выполнить GROUP BY после и ORDER BY следующим образом:

SELECT t.* FROM (SELECT * FROM table ORDER BY time DESC) t 
GROUP BY t.otheridentifier
Автор: 11101101b Размещён: 30.04.2013 03:14

2 плюса

2729 Репутация автора

Вы можете использовать этот запрос, чтобы получить правильный ответ:

SELECT * FROM 
      (SELECT * FROM `table` order by time DESC)
          t group by otheridentifier
Автор: php Размещён: 08.01.2014 06:23

0 плюса

10 Репутация автора

Это также:

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.
Автор: user2450223 Размещён: 15.06.2016 06:41
32x32