PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Маркирайте несъседни периоди от време

generate_series()

generate_series() на PostgreSQL може да създаде изглед, който съдържа последователен списък от дати:

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;

Изразът select max(date) - min(date) from test може да е отклонено с едно.

Броят дни на месец

Един от начините за идентифициране на невалидни месеци е да създадете два изгледа. Първият отчита броя на ежедневните показания, които всяка станция трябва да произвежда за всеки месец. (Имайте предвид, че climate.calendar се превежда на climate_calendar .) Второто връща действителните дневни показания, произведени от всяка станция за месец.

Максимален брой дни на месец на станция

Този изглед ще върне действителния брой дни в месеца за станция. (Например февруари винаги ще има 28 или 29 дни.)

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

Действителни дни на месец на станция

Общият брой върнати дни ще бъде по-малък от сумите. (Например януари винаги ще има 31 дни или по-малко.)

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;

Пуснете ORDER BY клаузи в производството (те са полезни при разработването).

Сравнете изгледите

Свържете двата изгледа, за да идентифицирате станциите и месеците, които трябва да бъдат маркирани, в нов изглед:

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

Колоната num_days_missing не е необходимо, но е полезно.

Това са редовете, които трябва да бъдат актуализирани:

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

Актуализиране на база данни

За да ги актуализирате, id ключът е удобен.

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. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как бързо да получите 13 линия за запис близо до точка (дължина, ширина) postgis

  2. Най-добрият начин за преброяване на записи на произволни интервали от време в Rails+Postgres

  3. Предаване на C променливи в SQL команда

  4. PostgreSQL променя реда на върнатите редове

  5. Как да конвертирам двойка географска ширина/дължина в географски тип PostGIS?