generate_series()
generate_series()
на PostgreSQL може да създаде изглед, който съдържа последователен списък от дати:
with calendar as (
select ((select min(date) from test)::date + (n || ' days')::interval)::date cal_date
from generate_series(0, (select max(date) - min(date) from test)) n
)
select cal_date
from calendar c
left join test t on t.date = c.cal_date
where t.date is null;
Изразът select max(date) - min(date) from test
може да е отклонено с едно.
Броят дни на месец
Един от начините за идентифициране на невалидни месеци е да създадете два изгледа. Първият отчита броя на ежедневните показания, които всяка станция трябва да произвежда за всеки месец. (Имайте предвид, че climate.calendar
се превежда на climate_calendar
.) Второто връща действителните дневни показания, произведени от всяка станция за месец.
Максимален брой дни на месец на станция
Този изглед ще върне действителния брой дни в месеца за станция. (Например февруари винаги ще има 28 или 29 дни.)
create view count_max_station_calendar_days as
with calendar as (
select ((select min(d) from climate_calendar)::date + (n || ' days')::interval)::date cal_date
from generate_series(0, (select max(d) - min(d) from climate_calendar)) n
)
select n, extract(year from cal_date) yr, extract(month from cal_date) mo, count(*) num_days
from stations cross join calendar
group by n, yr, mo
order by n, yr, mo
Действителни дни на месец на станция
Общият брой върнати дни ще бъде по-малък от сумите. (Например януари винаги ще има 31 дни или по-малко.)
create view count_actual_station_calendar_days as
select n, extract(year from d) yr, extract(month from d) mo, count(*) num_days
from climate_calendar
group by n, yr, mo
order by n, yr, mo;
Пуснете ORDER BY
клаузи в производството (те са полезни при разработването).
Сравнете изгледите
Свържете двата изгледа, за да идентифицирате станциите и месеците, които трябва да бъдат маркирани, в нов изглед:
create view invalid_station_months as
select m.n, m.yr, m.mo, m.num_days - a.num_days num_days_missing
from count_max_station_calendar_days m
inner join count_actual_station_calendar_days a
on (m.n = a.n and m.yr = a.yr and m.mo = a.mo and m.num_days <> a.num_days)
n yr mo num_days_missing
--
A 1982 1 1
E 2007 3 1
Колоната num_days_missing
не е необходимо, но е полезно.
Това са редовете, които трябва да бъдат актуализирани:
select cc.*
from climate_calendar cc
inner join invalid_station_months im
on (cc.n = im.n and
extract(year from cc.d) = im.yr and
extract(month from cc.d) = im.mo)
where valid = true
Актуализиране на база данни
За да ги актуализирате, id
ключът е удобен.
update climate_calendar
set valid = false
where id in (
select id
from climate_calendar cc
inner join invalid_station_months im
on (cc.n = im.n and
extract(year from cc.d) = im.yr and
extract(month from cc.d) = im.mo)
where valid = true
);