以下のような値のセットを持つPostgreSQL 11のテーブルがあるとします。
12 18
11 12
5 12
9 18
7 19
14 18
11 16
6 12
4 11
5 9
副選択を使用せずに選択を行う方法、または関数またはトリガー/関数を使用して選択を行って、各値が前の値よりも低いか、または前の値よりも高い可能性があるが、この例は前の値よりも低い(2行または15+行)列と最初の列の両方が最後の行よりも高くなったか、または最初と2番目の列の両方が選択を終了して条件を正にしましたか?
Select内に現在の変数を含める方法がわかりません。ルックバック変数を保持できれば、これを実行できるはずです。私はこれまでにこれに遭遇してこれをselect内で動作させたか、データベースの外にGoLang/Python/C++/Perl/PHP /など。データベースを離れると非常に簡単に実行できますが、これをPostgreSQL 11内で維持したいと思っています。
Akina がコメントで指摘したように、 LAG( )関数では、適切な値を表示するためにORDER BY句が必要です。
次の例を考えてみましょう:
CREATE TABLE t (id int, bar int);
INSERT INTO t VALUES
(1, 7),
(2, 8),
(3, 30),
(4, 25),
(5, 24),
(6, 24),
(7, 35),
(8, 40);
以前のbar
値はid
の順序で取得できます(順序を設定しない場合、前の行は何ですか?)
SELECT
id,
bar,
LAG(bar) OVER (ORDER BY id)
FROM
t;
id | bar | lag
-: | --: | ---:
1 | 7 | null --<< Note the NULL value
2 | 8 | 7
3 | 30 | 8
4 | 25 | 30
5 | 24 | 25
6 | 24 | 24
7 | 35 | 24
8 | 40 | 35
次に、単純に 条件ステートメント IFまたはCASEを使用します
SELECT
id,
bar,
CASE
WHEN LAG(bar) OVER (ORDER BY id) < bar THEN 'Lower'
WHEN LAG(bar) OVER (ORDER BY id) > bar THEN 'Higher'
WHEN LAG(bar) OVER (ORDER BY id) = bar THEN 'Equal'
ELSE 'Nothing to compare'
END As Previous
FROM
t;
id | bar | previous
-: | --: | :-----------------
1 | 7 | Nothing to compare
2 | 8 | Lower
3 | 30 | Lower
4 | 25 | Higher
5 | 24 | Higher
6 | 24 | Equal
7 | 35 | Lower
8 | 40 | Lower
db <> fiddle ここ
Plpgsqlでストアドプロシージャを記述して、SQLの手続き型動作にアクセスできますが、SQLの基礎であるセットベースのリレーショナルエイジブラを理解すれば、PostgreSQLを最大限に活用できます。
まず第一に、テーブル(別名リレーション)は基本的にタプル/レコードの順序付けされていないセットであり、順序付けられたシーケンスではないことを理解する必要があります。 Orderは、ORDER BYを介したクエリのプロパティであり、テーブル自体のプロパティではありません。いつでも、それは明らかにメモリやディスクに何らかの順序で格納されていますが、その順序に依存して維持することはできません。
いくつかのplpgsqlについては、次を参照してください。
https://carto.com/help/working-with-data/sql-stored-procedures/https://www.postgresql.org/docs/11/plpgsql-control -structures.html#PLPGSQL-RECORDS-ITERATING