Reputation: 9559
I have a table called Session in MySQL which looks like this:
+-----+---------------------+---------------------+--------------------+
| id | start | finish | name |
+-----+---------------------+---------------------+--------------------+
| -12 | 2013-04-27 09:00:00 | 2013-04-27 13:00:00 | Saturday Setup 1 |
| -11 | 2013-04-27 13:00:00 | 2013-04-27 18:00:00 | Saturday Setup 2 |
| -10 | 2013-04-27 23:00:00 | 2013-04-28 08:00:00 | Saturday Night |
| -3 | 2013-04-28 08:00:00 | 2013-04-28 13:00:00 | Sunday Setup 1 |
| -2 | 2013-04-28 13:00:00 | 2013-04-28 18:00:00 | Sunday Setup 2 |
| -1 | 2013-04-28 23:00:00 | 2013-04-29 08:00:00 | Sunday Night |
| 1 | 2013-04-29 09:00:00 | 2013-04-29 13:00:00 | Monday Setup 1 |
| 2 | 2013-04-29 13:00:00 | 2013-04-29 17:00:00 | Monday Setup 2 |
| 3 | 2013-04-29 17:00:00 | 2013-04-29 21:00:00 | Monday Setup 3 |
| 4 | 2013-04-29 23:00:00 | 2013-04-30 08:00:00 | Monday Night |
| 10 | 2013-04-30 09:00:00 | 2013-04-30 13:00:00 | Tuesday Setup 1 |
| 11 | 2013-04-30 13:00:00 | 2013-04-30 17:00:00 | Tuesday Setup 2 |
| 12 | 2013-04-30 23:00:00 | 2013-05-01 08:00:00 | Tuesday Night |
more rows etc...
I want to create a query which will select all columns in the table, with an additional column showing the next id on the same day (if any) when ordered by Start.
The result would look like this:
+-----+--------+---------------------+---------------------+--------------------+
| id | nextid | start | finish | name |
+-----+--------+---------------------+---------------------+--------------------+
| -12 | -11 | 2013-04-27 09:00:00 | 2013-04-27 13:00:00 | Saturday Setup 1 |
| -11 | -10 | 2013-04-27 13:00:00 | 2013-04-27 18:00:00 | Saturday Setup 2 |
| -10 | | 2013-04-27 23:00:00 | 2013-04-28 08:00:00 | Saturday Night |
| -3 | -2 | 2013-04-28 08:00:00 | 2013-04-28 13:00:00 | Sunday Setup 1 |
| -2 | -1 | 2013-04-28 13:00:00 | 2013-04-28 18:00:00 | Sunday Setup 2 |
| -1 | | 2013-04-28 23:00:00 | 2013-04-29 08:00:00 | Sunday Night |
| 1 | 2 | 2013-04-29 09:00:00 | 2013-04-29 13:00:00 | Monday Setup 1 |
| 2 | 3 | 2013-04-29 13:00:00 | 2013-04-29 17:00:00 | Monday Setup 2 |
| 3 | 4 | 2013-04-29 17:00:00 | 2013-04-29 21:00:00 | Monday Setup 3 |
| 4 | | 2013-04-29 23:00:00 | 2013-04-30 08:00:00 | Monday Night |
| 10 | 11 | 2013-04-30 09:00:00 | 2013-04-30 13:00:00 | Tuesday Setup 1 |
| 11 | 12 | 2013-04-30 13:00:00 | 2013-04-30 17:00:00 | Tuesday Setup 2 |
| 12 | | 2013-04-30 23:00:00 | 2013-05-01 08:00:00 | Tuesday Night |
more rows etc...
Any suggestions would be appreciated...
Upvotes: 1
Views: 153
Reputation: 1269493
This is a place where I think correlated subqueries are useful:
select id,
(select id from session s2 where date(s.start) = date(s2.start) order by start desc limit 1
) as nextId
start, finish, name
from session s
Upvotes: 1
Reputation: 589
I am not sure but you can try this
Lastly your MySql should be 5.4+
Upvotes: 1
Reputation: 21513
Using the start date to decide if the days match, something like this should do it. A subselect to get the min id which is larger than another id for the same day. Not tested I'm afraid.
SELECT a.id, Sub1.MinId AS nextid, a.start, a.finish, a.name
FROM SomeTable a
LEFT OUTER JOIN (SELECT a.id, MIN(b.id) AS MinId
FROM SomeTable a
INNER JOIN SomeTable b
ON DATE(a.start) = DATE(b.start)
AND a.id < b.id
GROUP BY a.id) Sub1
ON a.id = Sub1.id
Or is id is not in start order
SELECT a.id, c.id AS nextid, a.start, a.finish, a.name
FROM SomeTable a
LEFT OUTER JOIN (SELECT a.id, MIN(b.start) AS MinStart
FROM SomeTable a
INNER JOIN SomeTable b
ON DATE(a.start) = DATE(b.start)
AND a.id < b.id
GROUP BY a.id) Sub1
ON a.id = Sub1.id
LEFT OUTER JOIN SomeTable c
ON Sub1.MinStart = c.start
Upvotes: 0
Reputation: 125835
It won't be very efficient, as indexes cannot be used to evaluate the self-join criterion DATE(..) = DATE(..)
, but you're essentially trying to obtain the groupwise minimum:
SELECT cur.id, nxt.id nextid, cur.start, cur.finish, cur.name
FROM (
SELECT s1.*, MIN(s2.start) next
FROM Session s1
LEFT JOIN Session s2
ON DATE(s1.start) = DATE(s2.start)
AND s1.start < s2.start
GROUP BY s1.start
) cur LEFT JOIN Session nxt ON cur.next = nxt.start
See it on sqlfiddle.
Upvotes: 1