sql >> Databasteknik >  >> RDS >> PostgreSQL

Markera icke sammanhängande datumintervall

generate_series()

PostgreSQL:s generate_series() funktionen kan skapa en vy som innehåller en på varandra följande lista med datum:

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;

Uttrycket select max(date) - min(date) from test kan vara av med ett.

Räkna dagar per månad

Ett sätt att identifiera ogiltiga månader är att skapa två vyer. Den första räknar antalet dagliga avläsningar varje station ska producera under varje månad. (Observera att climate.calendar är översatt till climate_calendar .) Den andra returnerar de faktiska dagliga avläsningarna för varje station som produceras per månad.

Högsta antal dagar per månad per station

Den här vyn returnerar det faktiska antalet dagar i en månad, per station. (Till exempel kommer februari alltid att ha antingen 28 eller 29 dagar.)

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

Faktiska dagar per månad per station

Det totala antalet dagar som returneras kommer att vara färre än antalet. (Till exempel kommer januari alltid att ha 31 dagar 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;

Släpp ORDER BY klausuler i produktionen (de är till hjälp vid utveckling).

Jämför vyer

Gå med i de två vyerna för att identifiera de stationer och månader som behöver flaggas, till en ny vy:

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

Kolumnen num_days_missing är inte nödvändigt, men det är användbart.

Det här är raderna som behöver uppdateras:

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

Uppdatera databas

För att uppdatera dem, id nyckeln är bekväm.

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. PHP:Hur man visar en variabel (a) i en annan variabel (b) när variabel (b) innehåller text

  2. Postgresql:tar bort mellanslag mellan vissa typer av siffror

  3. Varför använder inte Postgres indexet?

  4. Hanterar innoDB dödläge