1

I found it really hard to come up with a descriptive problem title, so I'll give a bit of context.

We have a list of boats and a list of docks. Boats can be transferred from one dock to the other on a specific datetime, or it could be at no dock at all. I'm trying to find out which boats are at a specific dock at a given moment in time.

Here's a simplified SQL to illustrate the data model

CREATE TABLE `stackoverflow` (
  `boat_id` int(11) NOT NULL,
  `dock_id` int(11) DEFAULT NULL,
  `startingAt` datetime NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `stackoverflow` (`boat_id`, `dock_id`, `startingAt`)
VALUES
    (1, 1, '2020-01-01 00:00:00'),
    (1, 2, '2020-02-01 00:00:00'),
    (1, 3, '2020-03-01 00:00:00'),
    (2, 2, '2020-01-01 00:00:00'),
    (2, NULL, '2020-03-01 00:00:00');

The expected output for dock 1 and date 2020-01-15 would be 1.

The expected output for dock 2 and date 2020-02-15 would be 1, 2.

I've tried a lot of things including fancy joins but cannot get it to work. Any help is greatly appreciated!

0

1 Answer 1

1

You can use a correlated subquery to determine which boat is where at a given point in time. The rest is just filtering:

select s.*
from stackoverflow s
where s.startingAt = (select max(s2.startingAt)
                      from stackoverflow s2
                      where s2.boat_id = s.boat_id and
                            s2.startingAt <= '2020-02-15'  -- the time you care about
                     ) and
      s.dock_id = 2;

You can also use window functions to assign a time period for each boat at each dock:

select s.*
from (select s.*,
             lead(startingAt) over (partition by boat_id order by startingAt) as endingAt
      from stackoverflow s
     ) s
where s.startingAt <= '2020-02-15' and
      (s.endingAt > '2020-02-15' or s.endingAt is null) and
      s.dock_id = 2;

Here is a db<>fiddle.

Sign up to request clarification or add additional context in comments.

1 Comment

Great answer Gordon, thanks a lot! I've pulling my hair out using subselects already, but your answer nails it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.