PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Contrassegna intervalli di date non contigui

genera_serie()

generate_series() di PostgreSQL la funzione può creare una vista che contiene un elenco consecutivo di date:

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;

L'espressione select max(date) - min(date) from test potrebbe essere fuori di uno.

Conta giorni al mese

Un modo per identificare i mesi non validi consiste nel creare due viste. Il primo conta il numero di letture giornaliere che ogni stazione dovrebbe produrre in ogni mese. (Nota che climate.calendar è tradotto in climate_calendar .) Il secondo restituisce le letture giornaliere effettive prodotte da ciascuna stazione al mese.

Giorni massimi al mese per stazione

Questa visualizzazione restituirà il numero effettivo di giorni in un mese, per stazione. (Ad esempio, febbraio avrà sempre 28 o 29 giorni.)

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

Giorni effettivi al mese per stazione

Il numero totale di giorni restituiti sarà inferiore ai conteggi. (Ad esempio, gennaio avrà sempre 31 giorni o meno.)

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;

Rilascia ORDER BY clausole in produzione (sono utili per lo sviluppo).

Confronta visualizzazioni

Unisci le due viste per identificare le stazioni e i mesi che devono essere contrassegnati, in una nuova vista:

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

La colonna num_days_missing non è necessario, ma è utile.

Queste sono le righe che devono essere aggiornate:

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

Aggiorna database

Per aggiornarli, l'id la chiave è conveniente.

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
);