Моя таблица содержит данные журнала регистрации событий движения груза. Для отчетов требуется извлекать последний статус груза.
WAYBILL_NUMBER | EVENT_DATE | EVENT_NUM | EVENT_NAME | CITY_NAME | LOADED_TIME | EVENT_SEQ |
---|---|---|---|---|---|---|
1932875436 | 27/06/25 | 24 | Груз доставлен получателю | Солнечный(Магадан) | 27/06/25 | 11 |
1932875436 | 27/06/25 | 144 | Транзит по области | Солнечный(Магадан) | 27/06/25 | 10 |
1932875436 | 23/06/25 | 47 | Груз получен от поставщика | Магадан | 23/06/25 | 9 |
1932875436 | 22/06/25 | 23 | Груз отправлен | Москва | 22/06/25 | 8 |
1932875436 | 22/06/25 | 36 | Бронирование груза | Москва | 21/06/25 | 7 |
1932875436 | 21/06/25 | 71 | Груз сдан поставщику | Москва | 21/06/25 | 6 |
1932875436 | 21/06/25 | 22 | Груз манифестирован | Москва | 21/06/25 | 5 |
1932875436 | 21/06/25 | 117 | Автоматическое измерение груза | Москва | 21/06/25 | 4 |
1932875436 | 21/06/25 | 21 | Груз принят агентом | Москва | 21/06/25 | 3 |
1932875436 | 21/06/25 | 20 | Груз забран у отправителя | Москва | 21/06/25 | 2 |
1932875436 | 20/06/25 | 81 | Ввод накладной клиентом | Валищево | 20/06/25 | 1 |
В моей таблице примерно 169 тыс. записей (на каждую накладную от около 10 событий).
Вариант решения 1. Такой вариант довольно читабельный, на моей выборке первый запрос отработал за 0.56 сек. Последующие, кэшированные, отрабатывают за 0.08 сек.
SELECT WAYBILL_NUMBER, EVENT_NAME
FROM XXT_MAJOR2_EVENTS@OTM
WHERE (WAYBILL_NUMBER, EVENT_SEQ) IN (
SELECT WAYBILL_NUMBER, MAX(EVENT_SEQ)
FROM XXT_MAJOR2_EVENTS
GROUP BY WAYBILL_NUMBER)
ORDER BY WAYBILL_NUMBER DESC;
Вариант решения 2. С применением оконных функций - отрабатывает всегда одинаково по времени (~0.35 сек), потому что оконная функция ROW_NUMBER() работает каждый раз.
SELECT WAYBILL_NUMBER, EVENT_NAME
FROM
(SELECT WAYBILL_NUMBER, EVENT_NAME, EVENT_SEQ,
ROW_NUMBER() OVER (PARTITION BY WAYBILL_NUMBER ORDER BY EVENT_SEQ DESC) as rn FROM XXT_MAJOR2_EVENTS)
WHERE rn = 1
ORDER BY WAYBILL_NUMBER DESC
Несмотря на то, что кешированный вариант выглядит более привлекательнее, не факт, что в конечном итоге он будет верным выбором, потому что данные в таблицу добавляются ежедневно.
Примечательно также, что в процессе своих экспериментов я заметил разницу в данных. В какой-то из накладных EVENT_SEQ был null, по неизвестной причине. В таком случае строка не попадает в выборку при первом варианте.
Вообще заметил, что null в данных - это частый источник проблем, при чем не всегда неочевидных.