Вот другой подход, если поддерживается ANSI row_number()
:
with RevDayRanked(itemDate,rn) as (
select
cast(coll_date as date),
row_number() over (
partition by datediff(month,coll_date,'2000-01-01') -- rewrite datediff as needed for your platform
order by coll_date desc
)
from super_table
)
select itemDate
from RevDayRanked
where rn = 1;
Строки с номером 1 будут недетерминированно выбраны среди строк на последнюю активную дату месяца, поэтому вам не нужно различать. Если вы хотите получить информацию из таблицы для всех строк в эти даты, используйте rank()
по дням вместо row_number()
по значениям coll_date, поэтому значение 1 отображается для любой строки в последнюю активную дату месяца и выберите дополнительные столбцы, которые вам нужны:
with RevDayRanked(cust_id, server_name, coll_date, rk) as (
select
cust_id, server_name, coll_date,
rank() over (
partition by datediff(month,coll_date,'2000-01-01')
order by cast(coll_date as date) desc
)
from super_table
)
select cust_id, server_name, coll_date
from RevDayRanked
where rk = 1;
Если row_number()
и rank()
не поддерживаются, используется другой подход (для второго запроса выше). Выберите все строки в вашей таблице, для которых в таблице нет строк более позднего дня того же месяца.
select
cust_id, server_name, coll_date
from super_table as ST1
where not exists (
select *
from super_table as ST2
where datediff(month,ST1.coll_date,ST2.coll_date) = 0
and cast(ST2.coll_date as date) > cast(ST1.coll_date as date)
)
Если вам приходится много заниматься такими вещами, посмотрите, можете ли вы создать индекс по вычисляемым столбцам, которые содержат cast(coll_date as date)
, и индикатор месяца, например datediff(month,'2001-01-01',coll_date)
. Это сделает больше из предикатов SARG.