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

Markér ikke-sammenhængende datointervaller

generate_series()

PostgreSQL's generate_series() funktion kan oprette en visning, der indeholder en fortløbende liste over datoer:

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;

Udtrykket select max(date) - min(date) from test kan være slukket én gang.

Tæl dage pr. måned

En måde at identificere ugyldige måneder på er at oprette to visninger. Den første tæller antallet af daglige aflæsninger, hver station skal producere i hver måned. (Bemærk at climate.calendar er oversat til climate_calendar .) Den anden returnerer de faktiske daglige aflæsninger hver station produceret pr. måned.

Maksimalt antal dage pr. måned pr. station

Denne visning returnerer det faktiske antal dage i en måned pr. station. (For eksempel vil februar altid have enten 28 eller 29 dage.)

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

Faktiske dage pr. måned pr. station

Det samlede antal returnerede dage vil være færre end opgørelserne. (F.eks. vil januar altid have 31 dage eller færre.)

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;

Slip ORDER BY klausuler i produktionen (de er nyttige i udviklingen).

Sammenlign visninger

Slut dig til de to visninger for at identificere de stationer og måneder, der skal markeres, til en ny visning:

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

Kolonnen num_days_missing er ikke nødvendigt, men det er nyttigt.

Dette er de rækker, der skal opdateres:

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

Opdater database

For at opdatere dem skal du bruge id nøglen er praktisk.

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


  1. 15 Nyttige MySQL/MariaDB-tip til justering af ydeevne og optimering

  2. Bruger du jquery nedtællingstimer med mysql datetime?

  3. Hvorfor kommer planlæggeren med forskellige resultater for funktioner med forskellig volatilitet?

  4. Begræns med betinget værdikontrol i MySQL