質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Q&A

解決済

1回答

2497閲覧

時系列テーブルの欠損値の補完方法

horaotank

総合スコア1

PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

0グッド

0クリップ

投稿2020/09/01 04:42

前提・実現したいこと

PostgreSQLにある時系列テーブルの一部カラムの欠損値を補完をする方法を探しています。
下記の例ように一部カラムに欠損値がある場合に直近に存在する有効な値で補完させたいです。
レコードに欠損値をなくすことを目的としているので、更新処理が必要になります。

補完対象のテーブル例

time_id data1 data2 20200501 1000 2000 20200502 [null] [null] 20200503 1200 [null] 20200504 [null] 3000

補完後の目標のテーブル

time_id data1 data2 20200501 1000 2000 20200502 1000 2000 20200503 1200 2000 20200504 1200 3000

試したこと

検索すると値の取得のみであればウィンドウ関数を駆使すればできそうでしたが、更新が必要になるため実現方法を模索中です。
SQLに限らずアドバイス等頂ければ幸いです。

補足情報(FW/ツールのバージョンなど)

PostgreSQL(9.6.5)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2020/09/01 06:06

欠損値のない状態で処理することが多いのであれば、欠損値を埋める処理を別途検討の上で対応することをおすすめします。 おそらく、欠損値を埋めるのをリアルタイムにクエリー実行時に行うとサブクエリーを駆使して結構な負荷がかかりそうで、そういうリクエストがどのくらいの処理オーダーなのかによってはデータベースに掛かる負担も爆上げになりそうな気がします。処理で詰めたデータかどうかを判別するフラグも持たせればいいわけで。
horaotank

2020/09/01 08:27

ご連絡ありがとうございます。 SQLで解決するのはDB負荷的に難しいということで欠損値があるレコードを作成しないようにする方向で対応しようと思います。
guest

回答1

0

ベストアンサー

ウィンドウ関数で副問い合わせでSELECT文を作りその値でUPDATEする方法です。
PostgreSQLはIGNORE NULLSに対応してなかったようなので、
ありとなしで2パターン用意してあります。

負荷的には例に上がっている4件のデータで試しただけなので、
大量にデータがある場合に使えるかは何とも言えません。

またSAMPLE_TABLEはこちらで勝手に定義した仮のテーブル名です。

IGNORE NULLS使用

SQL

1UPDATE SAMPLE_TABLE S1 2SET (DATA1, DATA2) = ( 3SELECT PREV_DATA1, PREV_DATA2 4FROM ( 5 SELECT 6 SAMPLE_TABLE.*, 7 LAST_VALUE(DATA1 IGNORE NULLS) OVER(ORDER BY TIME_ID ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS PREV_DATA1, 8 LAST_VALUE(DATA2 IGNORE NULLS) OVER(ORDER BY TIME_ID ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS PREV_DATA2 9 FROM SAMPLE_TABLE 10 ) S2 11 WHERE S1.TIME_ID = S2.TIME_ID 12);

IGNORE NULLS不使用

SQL

1UPDATE SAMPLE_TABLE S1 2SET (DATA1, DATA2) = ( 3SELECT PREV_DATA1, PREV_DATA2 4FROM ( 5 SELECT 6 S.*, 7 FIRST_VALUE(DATA1) OVER (PARTITION BY GRP1) AS PREV_DATA1, 8 FIRST_VALUE(DATA2) OVER (PARTITION BY GRP2) AS PREV_DATA2 9 FROM ( 10 SELECT 11 SAMPLE_TABLE.*, 12 SUM(CASE WHEN DATA1 IS NOT NULL THEN 1 END) OVER (ORDER BY TIME_ID) AS GRP1, 13 SUM(CASE WHEN DATA2 IS NOT NULL THEN 1 END) OVER (ORDER BY TIME_ID) AS GRP2 14 FROM SAMPLE_TABLE 15 ) S 16 ) S2 17 WHERE S1.TIME_ID = S2.TIME_ID 18);

投稿2020/09/01 07:07

yureighost

総合スコア2183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

horaotank

2020/09/01 08:28

ご回答ありがとうございます。 レコードが少ないテーブルでは問題なく実行できましたが、レコードの多いテーブルだと実行時間的に実用できそうにありませんでした。 レコード追加時に欠損値がある状態を作らないようにする方向で再検討してみようと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問