简体   繁体   中英

Why mysql query is returning wrong Results?

I am attempting to find the latest log entries in my MySQL database. I cooked up this query late last night but upon testing today it does not seem to be returning the correct data.

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

The query runs just fine, but none of the other fields seem to match the id column. It grabs the max id number, but the hostName, email, and info do not match the id, and they are not the latest. I've spent a few hours spinning my wheels on this (I'm a MySQL noob and just doing this for fun) so I'm pretty confused now..

Thanks for any help!

EDIT: Wow thanks for all the responses! Sorry for the confusion, I should have said "I want the latest log per hostname!" <- That is specifically what I need.

You said:

I am attempting to find the latest log entries in my MySQL database

There is no need to group nor use a subquery. Just try this:

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

Now you said:

I want the latest log per hostname!

Then the solution should be this:

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

If you want the full row that corresponds to the max id for each distinct 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

Another way to do the same thing is to GROUP BY and then JOIN to the log table:

If "latest" means the maximum id , use a (hostname, time, id) index and this:

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 ;

UPDATE : You may alo want to try this one. It just might be more efficient (depending on the hostname distribution) - and would benefit from a index: (hostname, id, time) index:

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) ;

If "latest" means the maximum time (eg if time is insertion_time and is not changed later), use a (hostname, time) index and this:

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 ;

And finally, since everyone forgot to answer the "Why mysql query is returning wrong Results?" question, here is another question with some useful answers: Why does MySQL add a feature that conflicts with SQL standards?

This is a famous one:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM