PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Markieren Sie nicht zusammenhängende Datumsbereiche

generate_series()

generate_series() von PostgreSQL Funktion kann eine Ansicht erstellen, die eine fortlaufende Liste von Daten enthält:

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;

Der Ausdruck select max(date) - min(date) from test könnte um eins daneben liegen.

Tage pro Monat zählen

Eine Möglichkeit, ungültige Monate zu identifizieren, besteht darin, zwei Ansichten zu erstellen. Die erste zählt die Anzahl der täglichen Messwerte, die jede Station in jedem Monat produzieren sollte. (Beachten Sie, dass climate.calendar wird übersetzt in climate_calendar .) Die zweite gibt die tatsächlichen täglichen Messwerte zurück, die jede Station pro Monat produziert hat.

Maximale Tage pro Monat und Station

Diese Ansicht gibt die tatsächliche Anzahl der Tage in einem Monat pro Station zurück. (Zum Beispiel hat der Februar immer entweder 28 oder 29 Tage.)

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

Tatsächliche Tage pro Monat und Station

Die Gesamtzahl der zurückgegebenen Tage ist geringer als die Gesamtzahl. (Zum Beispiel hat der Januar immer 31 Tage oder weniger.)

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;

Lassen Sie ORDER BY fallen Klauseln in der Produktion (sie sind hilfreich bei der Entwicklung).

Ansichten vergleichen

Verbinden Sie die beiden Ansichten, um die Stationen und Monate zu identifizieren, die markiert werden müssen, in einer neuen Ansicht:

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

Die Spalte num_days_missing ist nicht notwendig, aber nützlich.

Dies sind die Zeilen, die aktualisiert werden müssen:

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

Datenbank aktualisieren

Um sie zu aktualisieren, muss die id Schlüssel ist praktisch.

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