简体   繁体   中英

SQL query to compare earlier values in the Table

We have a log table where user processes log entries ( success / failure / timeout ) each time they run. For eg

+----+----------+---------+
| id | username | status  |
+----+----------+---------+
|  1 | saqib    | success |
|  2 | mary     | timeout |
|  3 | scott    | timeout |
|  4 | saqib    | success |
|  5 | mary     | timeout |
|  6 | scott    | timeout |
|  7 | saqib    | timeout |
|  8 | mary     | timeout |
|  9 | scott    | timeout |
+----+----------+---------+

We would like to get a usernames which have had a success in the past the but the latest entry for them was a timeout. (saqib in the above example)

Is there single query that can do this? Right now we are doing this using a PHP script, but would like to use mySQL query for this.

Thanks

You can retrieve the latest id for each username and then JOIN it with the original table checking if there were entries for each user with status success and id less then maximum.

SELECT t.* 
FROM ( SELECT username
             , MAX(id) as ind
       FROM tbl
       GROUP BY username
     ) x JOIN tbl t ON t.username = x.username 
                   AND t.id = x.ind 
                   AND t.status IN ('timeout', 'failure')
                   AND EXISTS ( SELECT * 
                                FROM tbl 
                                WHERE username = x.username
                                  AND id < x.ind  
                                  AND status = 'success'
                              )

Example

SQL Fiddle

SELECT DISTINCT m1.username
FROM
(
  SELECT s1.username, s1.ids 
  FROM 
  (
    SELECT username, MAX(id) as ids
    FROM MyTable 
    GROUP BY username
  ) AS s1
  INNER JOIN MyTable AS s2
  ON s1.ids = s2.id
  WHERE s2.status = 'timeout'  
) AS m1
INNER JOIN MyTable m2 ON m1.username = m2.username
AND m2.status = 'success'

I would use exists for this problem. Exists are nice because they generally are faster than joining to the table. Unrelated, but I would recommend using a time stamp as opposed to relying on the id number.

Select username
From    table t1

Where   t1.status = 'timeout'

and     exists (Select 1
                From table t2
                Where t1.username = t2.username
                and     t2.status = 'success'
                Limit 1)

and     not exists (Select 1
                    From table t3
                    Where t3.username = t1.username
                    and     t3.id > t1.id
                        Limit 1);

You can join the table to itself:

SELECT GROUP_CONCAT(CONCAT_WS(' -> ', a.id, b.id) SEPARATOR ','), a.username
FROM t a
   JOIN t b USING (username)
WHERE b.id > a.id
   AND (a.status = 'success' 
   AND  b.status = 'timeout')
GROUP BY a.username;

This shows all pairs of previous success to later timeout.

SQLFiddle

SELECT 
 UserName, max(id)
 FROM TABLE
 WHERE 
    UserName IN (SELECT UserName from Table where Status = 'Success')
 GROUP BY UserName
    Having MAX(id) = (select max(id) from username where status = 'timeout')

You can do so by joining 2 subqueries 1 for the maximum id per user with success status which will satisfy the condition which have had a success in the past and 2 for the max id to get users with latest timeout last comparison part t1.id < t2.id will satisfy the user should have success in past

select * from
(select `username`,max(id) id 
from t 
where `status` ='success'
group by `username`
) t1
join
(
select `username`,max(id) id 
from t 
where `status` ='timeout'
group by `username`
  ) t2
on(t1.username = t2.username)
where t1.id < t2.id

Demo

Another solution this will be much cleaner bu just using one query with max and case

select
username,
max(case when `status` ='success' then id else 0 end) success,
max(case when `status` ='timeout' then id else 0 end) timeout
from t
group by username
having timeout > success
and success > 0

Demo 2

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