[解決済み] 最後の異なる値(赤方偏移)を取得するためのラグ関数
2022-02-12 01:10:35
質問
以下のようなサンプルデータがあり、目的のO/Pを得たいのですが、何かいい方法があれば教えてください。
3,4行目のprev_diff_valueのO/Pを次のようにしたい。 2015-01-01 00:00:00 代わりに 2015-01-02 00:00:00.
with dat as (
select 1 as id,'20150101 02:02:50'::timestamp as dt union all
select 1,'20150101 03:02:50'::timestamp union all
select 1,'20150101 04:02:50'::timestamp union all
select 1,'20150102 02:02:50'::timestamp union all
select 1,'20150102 02:02:50'::timestamp union all
select 1,'20150102 02:02:51'::timestamp union all
select 1,'20150103 02:02:50'::timestamp union all
select 2,'20150101 02:02:50'::timestamp union all
select 2,'20150101 03:02:50'::timestamp union all
select 2,'20150101 04:02:50'::timestamp union all
select 2,'20150102 02:02:50'::timestamp union all
select 1,'20150104 02:02:50'::timestamp
)-- select * from dat
select id , dt , lag(trunc(dt)) over(partition by id order by dt asc) prev_diff_value
from dat
order by id,dt desc
O/P :
id dt prev_diff_value
1 2015-01-04 02:02:50 2015-01-03 00:00:00
1 2015-01-03 02:02:50 2015-01-02 00:00:00
1 2015-01-02 02:02:51 2015-01-02 00:00:00
1 2015-01-02 02:02:50 2015-01-02 00:00:00
1 2015-01-02 02:02:50 2015-01-01 00:00:00
どのように解決するのですか?
id パーティション内の各タイムスタンプについて、前の異なる日付を取得したいのですね。その場合
lag
のユニークな組み合わせに対して
id
と
date
というように、元のデータセットに結合してください。
with dat as (
select 1 as id,'20150101 02:02:50'::timestamp as dt union all
select 1,'20150101 03:02:50'::timestamp union all
select 1,'20150101 04:02:50'::timestamp union all
select 1,'20150102 02:02:50'::timestamp union all
select 1,'20150102 02:02:50'::timestamp union all
select 1,'20150102 02:02:51'::timestamp union all
select 1,'20150103 02:02:50'::timestamp union all
select 2,'20150101 02:02:50'::timestamp union all
select 2,'20150101 03:02:50'::timestamp union all
select 2,'20150101 04:02:50'::timestamp union all
select 2,'20150102 02:02:50'::timestamp union all
select 1,'20150104 02:02:50'::timestamp
)
,dat_unique_lag as (
select *, lag(date) over(partition by id order by date asc) prev_diff_value
from (
select distinct id,trunc(dt) as date
from dat
)
)
select *
from dat
join dat_unique_lag
using (id)
where trunc(dat.dt)=dat_unique_lag.date
order by id,dt desc;
しかし、これは超高性能ではありません。もし、データの性質上、同じ日のタイムスタンプの数が限られている場合は、このような条件文を使ってラグを拡張することができます。
with dat as (
select 1 as id,'20150101 02:02:50'::timestamp as dt union all
select 1,'20150101 03:02:50'::timestamp union all
select 1,'20150101 04:02:50'::timestamp union all
select 1,'20150102 02:02:50'::timestamp union all
select 1,'20150102 02:02:50'::timestamp union all
select 1,'20150102 02:02:51'::timestamp union all
select 1,'20150103 02:02:50'::timestamp union all
select 2,'20150101 02:02:50'::timestamp union all
select 2,'20150101 03:02:50'::timestamp union all
select 2,'20150101 04:02:50'::timestamp union all
select 2,'20150102 02:02:50'::timestamp union all
select 1,'20150104 02:02:50'::timestamp
)
select id, dt,
case
when lag(trunc(dt)) over(partition by id order by dt asc)=trunc(dt)
then case
when lag(trunc(dt),2) over(partition by id order by dt asc)=trunc(dt)
then case
when lag(trunc(dt),3) over(partition by id order by dt asc)=trunc(dt)
then lag(trunc(dt),4) over(partition by id order by dt asc)
else lag(trunc(dt),3) over(partition by id order by dt asc)
end
else lag(trunc(dt),2) over(partition by id order by dt asc)
end
else lag(trunc(dt)) over(partition by id order by dt asc)
end as prev_diff_value
from dat
order by id,dt desc;
基本的には、前のレコードを見て、それが自分に合わなければ、その前のレコードに戻り、正しいレコードを見つけるか、発言の深さを使い果たすまで、そのレコードを探し続けます。ここでは、4つ前のレコードまで調べます。
関連
-
[解決済み】CREATE VIEW は、バッチ内の唯一のステートメントでなければなりません。
-
[解決済み】SQLが単一グループのグループ関数でないこと
-
[解決済み】ORA-01791: SELECTされた式ではない
-
[解決済み] SQL Server サブクエリが 1 つ以上の値を返しました。これは、サブクエリが =, !=, <, <= , >, >= のように続く場合は許可されません。
-
[解決済み] SQLクエリで2つの列から値を引き算する
-
[解決済み] varchar 値の変換で int カラムがオーバーフローしました。
-
[解決済み] 列名または提供された値の数がテーブル定義と一致しません。
-
[解決済み] SQLで複数のGROUP BYを使用する場合とは?
-
[解決済み] 各グループの最後のレコードを取得する - MySQL
-
[解決済み] mysqlのunionとorder by句の使い方
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】 "指定された集約関数を含まないクエリを実行しようとしました。"
-
[解決済み】CREATE VIEW は、バッチ内の唯一のステートメントでなければなりません。
-
[解決済み] テーブルのFROM句の項目がない [終了しました] 。
-
[解決済み】Postgresのエラー。式として使用されるサブクエリによって返される複数の行
-
[解決済み】SQL Server: 無効なカラム名
-
[解決済み] pg_restoreです。[archiver] 入力ファイルはテキスト形式のダンプであるように見えます。psql を使用してください。
-
[解決済み] SQL Server - 'RETURN'付近の、条件が想定されるコンテキストで指定された、非ブール型の式。
-
[解決済み] SELECT DISTINCTを指定した場合、ORDER BY項目は必ず選択リストに表示されます。
-
[解決済み] ORA-01735: 無効な ALTER TABLE オプション - ヒキガエル
-
[解決済み] Ruby On Rails で NuoDB を使用して SQL コマンドを手動で実行する方法