sql >> Base de Datos >  >> RDS >> PostgreSQL

Marcar intervalos de fechas no contiguos

generar_series()

generate_series() de PostgreSQL La función puede crear una vista que contenga una lista consecutiva de fechas:

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;

La expresión select max(date) - min(date) from test podría estar fuera por uno.

Contar días por mes

Una forma de identificar los meses no válidos es crear dos vistas. El primero cuenta el número de lecturas diarias que cada estación debe producir en cada mes. (Tenga en cuenta que climate.calendar se traduce a climate_calendar .) El segundo devuelve las lecturas diarias reales que cada estación produjo por mes.

Máximo de días al mes por estación

Esta vista devolverá el número real de días en un mes, por estación. (Por ejemplo, febrero siempre tendrá 28 o 29 días).

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

Días reales por mes por estación

El número total de días devueltos será menor que las cuentas. (Por ejemplo, enero siempre tendrá 31 días o menos).

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;

Suelta el ORDER BY cláusulas en producción (son útiles en el desarrollo).

Comparar vistas

Una las dos vistas para identificar las estaciones y los meses que deben marcarse en una nueva 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 columna num_days_missing no es necesario, pero es útil.

Estas son las filas que deben actualizarse:

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

Actualizar base de datos

Para actualizarlos, el id la clave es 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
);