tags:

views:

121

answers:

3

I should have paid more attention in relational databases class, so I need some help.

I have a table structured like so (there's more, but I'm only posting relevant info):

+------------------+-------------+------+-----+-------------------+-------+
| Field            | Type        | Null | Key | Default           | Extra |
+------------------+-------------+------+-----+-------------------+-------+
| session_id       | char(32)    | NO   |     | NULL              |       |
| file             | varchar(30) | NO   |     | NULL              |       |
| access_time      | timestamp   | NO   |     | CURRENT_TIMESTAMP |       |
+------------------+-------------+------+-----+-------------------+-------+`

I want to select the file field of the record with the greatest access_time for each session_id. So pretty much the last page visited in each session.

I've tried countless combinations of DISTINCT and the GROUP BY clause, but I can't seem to wrap my head around it for some reason. I'm using MySQL. Help please.

+1  A: 

I know this will work in SQL Server, and it should port to MySQL.

select session_id, timestamp, file 
from table t1
join (select session_id, max(timestamp) as timestamp) 
        from table group by session_id) as t2
   on t1.session_id = t2.session_id
     and t1.timestamp = t2.timestamp
ck
This only does it for one session_id; he asked for each.
MarkusQ
Was in the process of editing....
ck
That worked! (with a little tweaking). Here's the query I used: select t1.session_id, t1.access_time, t1.file from table AS t1 join (select session_id, max(access_time) as access_time from table group by session_id) as t2 on t1.session_id = t2.session_id and t1.access_time = t2.access_time;
Andrew
Glad you got there. Looking at it now, I can see you would get errors on session_id and timestamp as they are both there twice fro mthe two tables.
ck
@ck This is overly complex. My query below returns the same rows (despite your comment to the contrary) with a lot less fiddling about.
MarkusQ
+2  A: 
select * from my_table t1
    where t1.access_time = (
       select max(t2.access_time) 
         from my_table t2 
         where t2.session_id = t1.session_id
       )
MarkusQ
That will bring back files where the session time matches a session time for another session
ck
@ck No it won't. Read it more carefully. It only returns rows where the access_time equals the most recent access_time FOR THIS SESSION. That's what the where clause is for.
MarkusQ
Yes of course, you are right. This is normally the way I would do it, was just having a mental block.
ck
Thanks for the help. Unfortunately this method took considerably longer than ck's answer. I didn't even let the query finish because it was taking so long.
Andrew
How odd. It shouldn't be slower if things are set up reasonably. What indexes do you have?
MarkusQ
A: 
SELECT
     T1.session_id,
     T1.file,
     T1.access_time
FROM
     My_Table T1
LEFT OUTER JOIN My_Table T2 ON
     T2.session_id = T1.session_id AND
     T2.access_time > T1.access_time
WHERE
     T2.session_id IS NULL

If there are duplicate access_time values for the same session_id then you might get multiple rows for that session_id. You can tweak this to avoid that if needed depending on your business rules for that situation.

Tom H.