ТЛ; др
Вот код MySQL, который вам нужен:
SELECT bike_id FROM (
SELECT * FROM (
SELECT * FROM bikes
WHERE updated_on < '20181209'
ORDER BY updated_on DESC, id DESC
) AS sub
GROUP BY bike_id
) AS sub2
WHERE is_live = true
Почему это работает?
Нам нужно немного разбить вопрос. Мне нравится начинать с позиции «как я могу получить нужную мне информацию в формате, который имеет смысл для меня (как человека)?».
Итак, первое, что я сделал, это получил список всех велосипедов с датами updated_on
до 9-го декабря (т.е. были обновлены 8-го декабря или раньше). Я также заказал это по полю updated_on
, чтобы я (как человек) мог легко увидеть «последнюю» запись, которая сообщит мне самый последний статус каждого велосипеда до или 8-го декабря:
SELECT * FROM bikes
WHERE updated_on < '20181209'
ORDER BY updated_on DESC, id DESC
Из этого я вижу, что до 9-го декабря есть 5 записей об изменении статуса велосипеда. Я легко вижу, что для каждого велосипеда есть несколько записей «обновления», но теперь я могу начать с верхней части списка, и каждый идентификатор велосипеда, с которым я сталкиваюсь - это статус 8 декабря
Дополнительно я добавил order_by для идентификатора записи. Это необходимо, потому что может быть несколько обновлений в день. Сама дата не скажет нам, какое из этих обновлений было последним в тот же день, поэтому мы используем идентификатор, чтобы определить это. (при условии, что он хронологически инкрементален).
Теперь у нас есть список всех статусов и идентификаторов велосипедов в базе данных до 9 декабря, нам нужно ограничить это только одной записью на велосипед. Это легко, мы можем обернуть исходный запрос новым запросом с помощью директивы Group By на bike_id.
SELECT * FROM (
SELECT * FROM bikes
WHERE updated_on < '20181209'
ORDER BY updated_on DESC, id DESC
) AS sub
GROUP BY bike_id
Group By в MySQL выбирает первую найденную запись для каждой группы. Мы уже упорядочили список по date
и id
в исходном запросе, поэтому первая запись для каждого bike_id
будет самым последним состоянием для этого велосипеда по состоянию на 8 декабря
Теперь нам осталось только выбрать bike_id
и отфильтровать неживые велосипеды, используя WHERE is_live = true
в этом последнем запросе. Вот как мы получаем запрос в начале этого ответа:
SELECT bike_id FROM (
SELECT * FROM (
SELECT * FROM bikes
WHERE updated_on < '20181209'
ORDER BY updated_on DESC, id DESC
) AS sub
GROUP BY bike_id
) AS sub2
WHERE is_live = true
Надеюсь, это поможет.