generate_series()
PostgreSQLのgenerate_series()
関数は、日付の連続リストを含むビューを作成できます:
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
1つずれている可能性があります。
1か月あたりの日数を数える
無効な月を特定する1つの方法は、2つのビューを作成することです。 1つ目は、各ステーションが毎月生成する必要のある毎日の測定値の数をカウントします。 (climate.calendar
に注意してください climate_calendar
に変換されます 。)2番目は、各ステーションが1か月に生成した実際の毎日の測定値を返します。
ステーションあたりの1か月あたりの最大日数
このビューは、ステーションごとの1か月の実際の日数を返します。 (たとえば、2月は常に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
ステーションごとの1か月あたりの実際の日数
返される合計日数は、集計よりも少なくなります。 (たとえば、1月は常に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
を削除します 本番環境の句(開発に役立ちます)。
ビューの比較
2つのビューを結合して、フラグを立てる必要のあるステーションと月を特定し、新しいビューにします。
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
);