#sql
#sql
Вопрос:
Я пытаюсь выполнить запрос, который возвращает значение последней опубликованной версии. Версии могут быть названы V1, V2, R1_V1, R1_V2, R2_V1, R2_V2 и опубликованы в этом порядке. Первым сообщением всегда будет #null. Не все версии зависят, я имею в виду, что первая версия дня может быть зарегистрирована как R1_V1 без предварительной публикации V1 и V2.
Версии содержат почасовые журналы, поэтому я всегда должен использовать последнюю версию.
Вот краткий пример:
Комментарии:
1. Итак, в чем ваш вопрос? Какую СУБД вы действительно используете?
Ответ №1:
В следующий раз вставьте входные данные в виде текста в свой вопрос. Мне пришлось вручную все перепечатать….
Вам нужно дополнительное значение сортировки в дополнение к версии; затем вам нужно добавить значение фильтра на основе порядка сортировки. Используйте функцию OLAP.
WITH
-- your input ... not part of the final query
indata(dt,ver,val) AS (
SELECT DATE '2020-02-01',NULL ,1.1
UNION ALL SELECT DATE '2020-02-01','V1' ,1
UNION ALL SELECT DATE '2020-02-01','R1_V1',1.5
UNION ALL SELECT DATE '2020-02-02',NULL ,1.2
UNION ALL SELECT DATE '2020-02-03',NULL ,1.3
UNION ALL SELECT DATE '2020-02-03','V1' ,1.5
UNION ALL SELECT DATE '2020-02-03','R1_V1',1.2
UNION ALL SELECT DATE '2020-02-03','R1_V2',1.3
)
-- end of your input, query starts below, replace ',' with 'WITH' ...
,
-- add a sorting integer. 0 if "ver" is NULL, 1 if it's 'V1', 2 otherwise
w_sort AS (
SELECT
*
, CASE
WHEN ver IS NULL THEN 0
WHEN ver = 'V1' THEN 1
ELSE 2
END AS srt
FROM indata
)
,
-- add a filtering integer that is at 1 with the max order value
-- on the sorting criteria, so sort descending
w_fltr AS (
SELECT
*
, ROW_NUMBER() OVER(PARTITION BY dt ORDER BY srt DESC, ver DESC) AS fl
FROM w_sort
)
-- finally filter by the filter value created above, at 1
SELECT
dt
, ver
, val
FROM w_fltr
WHERE fl=1;
-- out dt | ver | val
-- out ------------ ------- -----
-- out 2020-02-01 | R1_V1 | 1.5
-- out 2020-02-02 | | 1.2
-- out 2020-02-03 | R1_V2 | 1.3
Комментарии:
1. Спасибо за вашу помощь и извините за неудобство, я приму к сведению в следующий раз, я впервые задаю здесь вопросы.
Ответ №2:
Вы можете использовать оконные функции:
select t.*
from (select t.*,
row_number() over (partition by date
order by (case when version not like '%_%' then 1 else 2 end) desc,
version desc
) as seqnum
from t
) t
where seqnum = 1;