PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Marquer des plages de dates non contiguës

generate_series()

generate_series() de PostgreSQL La fonction peut créer une vue contenant une liste consécutive de dates :

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'expression select max(date) - min(date) from test peut être décalé d'un.

Compter les jours par mois

Une façon d'identifier les mois non valides consiste à créer deux vues. Le premier compte le nombre de lectures quotidiennes que chaque station devrait produire chaque mois. (Notez que climate.calendar est traduit en climate_calendar .) La seconde renvoie les lectures quotidiennes réelles produites par chaque station par mois.

Nombre maximum de jours par mois et par station

Cette vue renverra le nombre réel de jours dans un mois, par station. (Par exemple, février aura toujours 28 ou 29 jours.)

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

Jours réels par mois et par station

Le nombre total de jours renvoyés sera inférieur aux décomptes. (Par exemple, janvier aura toujours 31 jours ou moins.)

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;

Déposez le ORDER BY clauses en production (elles sont utiles en développement).

Comparer les vues

Joignez les deux vues pour identifier les stations et les mois qui doivent être signalés, dans une nouvelle vue :

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 colonne num_days_missing n'est pas nécessaire, mais c'est utile.

Voici les lignes qui doivent être mises à jour :

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

Mettre à jour la base de données

Pour les mettre à jour, l'id clé est pratique.

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