LINUX.ORG.RU
решено ФорумAdmin

HyperSQL запрос на получение последнего статуса при условии

 ,


0

1

Есть таблица вида

ID Obj      Stat   Stat_date
1  Объект1  1      01.01.2023
2  Объект2  2      02.03.2023
3  Объект1  2      22.08.2023
4  Объект3  2      15.09.2023
5  Объект4  1      01.02.2023
6  Объект3  3      21.09.2023

Я все представляю упрощенно, чтобы не вмешивать лишнее. На самом деле в базе 5 таблиц, один связаны друг с другом и т. п.

Как видно, это вроде истории изменения статуса объектов. В этой таблице у объекта может быть много статусов. Я пытаюсь сформировать запрос, который выдаст мне

все объекты, чей *последний* за последние 300 дней равен 2

Если решать это в лоб, как попробовал я, получается результат, который мне не нужен:

SELECT ID, Obj, Stat, Stat_date
WHERE DATEDIFF('day', Stat_date, CURRENT_DATE) <= 300 AND Stat = 2

При таком запросе в результат попадут Объект1, Объект2, Объект3, хотя Объект3 последним статусом имеет 3, а не 2. Получается, последовательность фильтров это не последовательность, а одновременно применение. Подозреваю, что мне нужны два отдельных SELECT или какой-то комплексный фильтр, чтобы применять внутри него фильтры последовательно (каждый последующий фильтр обрабатывает результаты предыдущего), но не понимаю, как это сделать.

P.S. Не хватает тегов hsqldb/hypersql.

Перемещено hobbit из general

Пока ждал ответа, догадался про сортировку.

SELECT TOP 1 ID, Obj, Stat, Stat_date
WHERE DATEDIFF('day', Stat_date, CURRENT_DATE) <= 300 AND Stat = 2
ORDER BY Stat_date DESC

Сортируем по дате (хорошо, что она есть в таблице) от раннего к позднему и берем первый результат.

demonworm
() автор топика
Ответ на: комментарий от demonworm

Я бы подождал ещё, потому что это некорректно.

Кстати, вот, держи

select * from tbl where ( obj, stat_date ) in ( select obj, max( stat_date ) from tbl group by obj ) and stat = 2

А 300 дней тебе вообще хз зачем? Чтобы вообще не учитывать объекты, статус которых менялся последний раз давнЕЕ?

mrjaggers
()
Ответ на: комментарий от mrjaggers

А 300 дней тебе вообще хз зачем? Чтобы вообще не учитывать объекты, статус которых менялся последний раз давнЕЕ?

Да

select * from tbl where ( obj, stat_date ) in ( select obj, max( stat_date ) from tbl group by obj ) and stat = 2

Тут токены, которые HyperSQL не поддерживаются (какие - не знаю, видимо, IN).

Я бы подождал ещё, потому что это некорректно.

Можешь пояснить? Вроде результат правильный отдает. В чем некорректность?

demonworm
() автор топика
Ответ на: комментарий от demonworm

ты сразу выбрал только все строки где статус 2. И пофиг, последнее это изменение для каждого Obj или не последнее.

не знаю, что за хипер скуль, но IN он уж точно поддерживает. Он вполне может не поддерживать запись вида ( obj, stat_date ) in

ну перепиши на join (и добавь свои 300 дней ещё в конце)

задача банальная

mrjaggers
()
Ответ на: комментарий от demonworm

Тут токены, которые HyperSQL не поддерживаются

В HSQL Database Engine 2.7.2 - точно этот запрос работает.

Поставил посмотреть, что за зверь такой )

Ваш вариант с SELECT TOP 1 bla-bla совсем не по задаче выбирает.

Попробуйте с JOIN, как вам советовали. Типа такого:

SELECT t.*
FROM 
	lor_tab4 t
	JOIN (SELECT obj, max( status_date ) AS max_status_date FROM lor_tab4 GROUP BY obj) tm
		ON t.obj = tm.obj
		AND t.status_date = tm.max_status_date
WHERE t.status = 2 AND DATEDIFF('day', t.status_date, CURRENT_DATE) <= 300
;

Забавно, что в PostgreSQL планы запросов с IN, и с JOIN абсолютно одинаковые.

Hsqldb рисует разные планы, при одинаковом результате. Правда я этот hsqldb первый раз в глаза вижу - ни бельмеса не понял в его планах.

Toxo2 ★★★★
()
Последнее исправление: Toxo2 (всего исправлений: 1)
Ответ на: комментарий от Toxo2

Спасибо за рабочий пример. Все разобрал, все, вроде, понял.

Можно поподробнее про планы и посоветуй какой-нибудь учебник вменяемый учебник/гайд по SQL и запросам. Мне для собственных нужд, я не разработчик. Просто въехать в такие схемы запросов. Вообще планирую все же с sqlite3 работать, а не HyperSQL, но пока не получилось Libreoffice Base завести с sqlite3 (нужен фронт для запросов, форм и отчетов), поэтому сижу на стоковой базе.

demonworm
() автор топика
Ответ на: комментарий от demonworm

Можно поподробнее про планы

не надо тебе.

учебник вменяемый учебник/гайд по SQL

садиться и пейсать. Ну зелёная книжка есть какая-то ЕМНИП. Но я бы не зацикливался.

Мне для собственных нужд

тем более

не получилось Libreoffice Base завести с sqlite3

я завёл с полпинка пошукав интернет немного (их же оф. гайд в т.ч.). ЕМНИП ставишь скуляйт, одбс вроде на него настраиваешь и в либре при создании нового как он называется.. документа в Бейс выбираешь скуляйт.

mrjaggers
()