Выберите последнюю запись в таблице (поле даты и времени) - PullRequest
20 голосов
/ 25 января 2011

Я искал сайт для помощи, но все еще изо всех сил.Вот моя таблица:

messages
========
id
thread_id
user_id
subject
body
date_sent

В основном я хочу получить последнюю запись для каждого идентификатора потока.Я пробовал следующее:

SELECT id, thread_id, user_id, subject, body, date_sent
FROM messages
WHERE user_id=1 AND date_sent=(select max(date_sent))
GROUP BY thread_id
ORDER BY date_sent DESC

НО это дает мне самые старые записи, а не самые новые!

Кто-нибудь может посоветовать?

РЕДАКТИРОВАТЬ: Таблица дампа:

--
-- Table structure for table `messages`
--

CREATE TABLE IF NOT EXISTS `messages` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `thread_id` int(10) unsigned NOT NULL,
  `user_id` int(10) unsigned NOT NULL,
  `body` text NOT NULL,
  `date_sent` datetime NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=34 ;

--
-- Dumping data for table `messages`
--

INSERT INTO `messages` (`id`, `thread_id`, `user_id`, `body`, `date_sent`) VALUES
(1, 1, 1, 'Test Message', '2011-01-20 00:13:51'),
(2, 1, 6, 'Test Message', '2011-01-20 01:03:50'),
(3, 1, 6, 'Test Message', '2011-01-20 01:22:52'),
(4, 1, 6, 'Test Message', '2011-01-20 11:59:01'),
(5, 1, 1, 'Test Message', '2011-01-20 11:59:22'),
(6, 1, 6, 'Test Message', '2011-01-20 12:10:37'),
(7, 1, 1, 'Test Message', '2011-01-20 12:10:51'),
(8, 2, 6, 'Test Message', '2011-01-20 12:45:29'),
(9, 1, 6, 'Test Message', '2011-01-20 13:08:42'),
(10, 1, 1, 'Test Message', '2011-01-20 13:09:49'),
(11, 2, 1, 'Test Message', '2011-01-20 13:10:17'),
(12, 3, 1, 'Test Message', '2011-01-20 13:11:09'),
(13, 1, 1, 'Test Message', '2011-01-21 02:31:43'),
(14, 2, 1, 'Test Message', '2011-01-21 02:31:52'),
(15, 4, 1, 'Test Message', '2011-01-21 02:31:57'),
(16, 3, 1, 'Test Message', '2011-01-21 02:32:10'),
(17, 4, 6, 'Test Message', '2011-01-20 22:36:57'),
(20, 1, 6, 'Test Message', '2011-01-20 23:02:36'),
(21, 4, 1, 'Test Message', '2011-01-20 23:17:22');

РЕДАКТИРОВАТЬ: Извинения - я, возможно, немного запутался здесь - в основном я хочу, чтобы получить все сообщения для данного user_id, ТО найти последнее сообщение (для thread_id) из этих полученных сообщений.

Ответы [ 4 ]

34 голосов
/ 25 января 2011
SELECT id, thread_id, user_id, subject, body, date_sent
  FROM messages WHERE date_sent IN (
    SELECT MAX( date_sent )
      FROM messages WHERE user_id =6 GROUP BY thread_id
  )
  ORDER BY thread_id ASC , date_sent DESC;

Дайте мне знать, работает ли он сейчас

4 голосов
/ 25 января 2011

Это процесс с двумя остановками.Сначала найдите самые новые даты для каждого thread_id.Затем выберите записи, которые имеют эти даты и соответствуют thread_id s

SELECT t.id, t.thread_id, t.user_id, t.body, t.date_sent
FROM messages AS t
CROSS JOIN (
  SELECT thread_id, MAX(date_sent) AS date_sent FROM messages WHERE user_id = 1 GROUP BY thread_id
) AS sq
USING (thread_id, date_sent)

Обратите внимание, что если две (или более) messages имеют одинаковые date_sent и одинаковые thread_id, они оба будут выбраны (Вы не можете сказать, какой из них новее)

2 голосов
/ 14 марта 2015

Это действительно старый вопрос, но все равно ...

Ваше условие where недостаточно конкретное, и использование date_sent для выбора нужной записи просто неверно. Попробуйте это:

SELECT id, thread_id, user_id, subject, body, date_sent
FROM messages
WHERE id=(
    select m2.id from messages m2
    where messages.thread_id=m2.thread_id
    order by date_sent desc limit 1)
ORDER BY date_sent DESC

Если вы хотите предположить, что id всегда увеличивается со временем, это, вероятно, будет работать лучше:

SELECT id, thread_id, user_id, subject, body, date_sent
FROM messages
WHERE id in (
    select max(m2.id) from messages m2 group by m2.thread_id)
ORDER BY date_sent DESC
1 голос
/ 25 января 2011

Из того, что я вижу, ваша проблема связана с подзапросом.Подзапрос будет фактически извлекать максимальное поле date_sent из текущей записи, другими словами, поскольку внешний запрос пересекает таблицу по одной записи за раз, два поля date_sent в подзапросе "date_sent=(select max(date_sent)" всегда будуттот же самый.После того, как он отображает первую запись для определенного thread_id, он не показывает никаких других записей для этого thread_id, поскольку вы группируете по thread_id.Поэтому всегда будет отображаться первая запись, введенная для каждого идентификатора потока.Кстати, он показывает первую запись, введенную для каждого thread_id, а не самую раннюю запись date_sent.Ваш результат зависит от местоположения записи в вашей таблице, а не от значения date_sent.Не уверен, что я объяснил это правильно, но в любом случае, чтобы решить вашу проблему, попробуйте:

SELECT id, thread_id, user_id, subject, body, date_sent
FROM messages
WHERE user_id=1 AND date_sent IN (select max(date_sent) from messages GROUP BY thread_id)
GROUP BY thread_id
ORDER BY date_sent DESC;

Во-первых, подзапрос должен иметь предложение FROM и предложение GROUP BY, чтобы получить максимумдаты для thread_id из таблицы WHOLE, а не только из текущей записи.Кроме того, = необходимо заменить на IN, так как подзапрос может привести к нескольким записям.Если таблица содержит две записи с одинаковым идентификатором потока в одну и ту же дату, будет отображаться только первая.Это вызвано вторым предложением GROUP BY во внешнем запросе.Чтобы отобразить все записи для этого thread_id в этот день, попробуйте:

SELECT id, thread_id, user_id, subject, body, date_sent
FROM messages
WHERE user_id =1 AND date_sent IN (SELECT MAX( date_sent ) FROM messages GROUP BY thread_id)
ORDER BY thread_id ASC , date_sent DESC;

Удалив второе предложение GROUP BY и добавив предложение ORDER BY, вы можете показать все сообщения для этой максимальной даты для каждогоthread_id и по-прежнему отображать темы в правильном порядке.Надеюсь, это поможет.

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