2012-06-15 2 views
1

Я пытаюсь найти последние записи журнала в моей базе данных MySQL. Я приготовил этот запрос поздно вечером, но сегодня, после тестирования, похоже, что он не возвращает правильные данные.Почему mysql-запрос возвращает неправильные результаты?

SELECT MAX(id), hostName, email, info, time 
FROM log 
WHERE time >= DATE_SUB(NOW(), INTERVAL 1 HOUR) 
GROUP BY hostName 
ORDER BY `time` DESC 

Запрос выполняется просто отлично, но ни одно из других полей, похоже, не соответствует столбцу id. Он захватывает максимальный номер id, но имя узла, адрес электронной почты и информация не соответствуют идентификатору, и они не являются последними. Я потратил несколько часов на то, чтобы крутить мои колеса на этом (я MySQL noob и просто делаю это для удовольствия), поэтому я довольно запутался сейчас.

Спасибо за помощь!

EDIT: Wow благодарит за все ответы! Извините за путаницу, я должен был сказать: «Мне нужен последний журнал для имени хоста!» < - Это именно то, что мне нужно.

+0

Зачем вам нужен MAX()? Является ли упорядочение по времени недостаточным для получения последних записей журнала? –

+0

Хм .. просто удалил его, и я получаю данные, которые почти 30 минут. – David

+0

Можете ли вы объяснить результат, который хотите? «Только последняя запись каждого хоста и идентификатора»? – Akarun

ответ

1

Другой способ сделать то же самое, чтобы GROUP BY и затем JOIN в таблице журнала:

If «последняя» означает максимум id, используйте индекс (hostname, time, id) и это:

SELECT log.id 
FROM 
     log 
    JOIN 
     (SELECT MAX(id) AS id 
      FROM log 
      WHERE time >= DATE_SUB(NOW(), INTERVAL 1 HOUR) 
      GROUP BY hostName 
     ) AS grp 
     ON grp.id = log.id ; 

ОБНОВЛЕНИЕ: Вы можете попробовать это. Это как раз может быть более эффективным (в зависимости от распределения имени хоста) - и выиграли бы от индекса: (hostname, id, time) индекс:

SELECT log.id 
FROM 
     log 
    JOIN 
     (SELECT MAX(id) AS id 
      FROM log 
      GROUP BY hostName 
     ) AS grp 
     ON grp.id = log.id 
WHERE log.time >= DATE_SUB(NOW(), INTERVAL 1 HOUR) ; 

Если «последняя» означает максимальное time (например,если time является insertion_time и не изменяется позже), использовать (hostname, time) индекс и это:

SELECT log.* 
FROM 
     log 
    JOIN 
     (SELECT hostname, MAX(time) AS max_time 
      FROM log 
      WHERE time >= DATE_SUB(NOW(), INTERVAL 1 HOUR) 
      GROUP BY hostname 
     ) AS grp 
     ON grp.hostname = log.hostname 
     AND grp.max_time = log.time ; 

И, наконец, так как все забыли ответить на «Почему MySQL запрос возвращает неправильные результаты?» вопрос, вот еще один вопрос с некоторыми полезными ответами: Why does MySQL add a feature that conflicts with SQL standards?

+0

Спасибо, я считаю, что у меня есть индекс на id, так как это первичный ключ. Я изучаю добавление одного на имя хоста сейчас! :) – David

+1

Не на '(имя хоста)' но на '(hostname, id)' –

+0

Хм, я не думал о состоянии 'time'. Это будет непросто. –

0

Это известная один:

SELECT * 
FROM log 
WHERE log.id IN (
    SELECT MAX(id) 
    FROM log 
    WHERE time >= DATE_SUB(NOW(), INTERVAL 1 HOUR) 
    GROUP BY hostName) T 
1

Если вы хотите полную строку, которая соответствует максимальному идентификатору для каждого отдельного hostName,

SELECT id, hostName, email, info, time 
FROM log 
WHERE id IN 
    (SELECT MAX(id) FROM log WHERE time >= DATE_SUB(NOW(), INTERVAL 1 HOUR) 
    GROUP BY hostName) 
ORDER BY `time` DESC 
+0

Этот запрос занял 177 секунд для запуска O_O – David

+0

У вас есть полезный индекс для hostName? –

+0

Отрицательный. Я слышал об индексах и на самом деле должен начать исследовать их. Я попытаюсь добавить один. – David

2

Вы сказали:

Я пытаюсь найти последние записи журнала в моей базе данных MySQL

Нет необходимости группировать и использовать подзапрос. Просто попробуйте это:

SELECT id, hostName, email, info, time FROM log 
WHERE time >= DATE_SUB(NOW(), INTERVAL 1 HOUR) 
ORDER BY `time` DESC 

Теперь вы сказали:

Я хочу, чтобы последний журнал за имя хоста!

Затем раствор должен быть таким:

SELECT l1.id, l1.hostName, l1.email, l1.info, l1.time FROM log l1 
LEFT JOIN log l2 on l1.hostName = l2.hostName AND l1.time < l2.time 
WHERE l2.time IS NULL 
ORDER BY l1.time DESC 
+0

Спасибо, но я ищу специально для одного журнала для имени хоста! – David

+0

Совсем другой вопрос! –

+0

Я знаю, я плохо разбираюсь в вещах, которые я не знаю хорошо * смущен * – David

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