statut_existenta_pf
テーブルに時間ベースのオブジェクト インスタンスを保持しているようです。
次のテストベッドを使用しました。
CREATE TABLE statut_existenta_pf (
se_id int4,
se_id_pf int4,
se_id_statut int2,
se_data_inceput date,
se_data_sfarsit date
); -- the rest fields are irrelevant for this example
CREATE TABLE nom_statut_existenta (
id int2,
ne_denumire varchar(30)
); -- my wild guess bout this table
CREATE TABLE persoane_fizice (
pf_id int4,
pf_name varchar(60)
); --- same here, irrelevant for the example
次のテスト データを使用します。
INSERT INTO nom_statut_existenta VALUES
(1, 'Status: Vive'), (2, 'Status: Morto');
INSERT INTO persoane_fizice VALUES (3489, 'Giuseppe Garibaldi');
INSERT INTO statut_existenta_pf VALUES
(4275, 3489, 2, '2012-04-18', '2012-05-18'),
(3669, 3489, 1, '2010-03-31', NULL);
ここで、この時系列シリーズで現在のオブジェクトを検索しています。あなたのロジックは次のようです:
se_data_inceput
である場合NULL
(この列を として扱いますinstance_start_date
)、指定された の最新のリビジョンの値を取得しますpersoane_fizice
。
- もしそうなら
se_data_sfarsit
(NULL
私instance_end_date
は信じています)、再び、最新のリビジョンの値を取得します。
- 両方の列が の場合
NOT NULL
、そのような日付の間にあるリビジョンの値を取得します。
セットアップの制約については何も言及していませんが、日付範囲が重複する複数のエントリを持つことは違法であると思います。
最初のクエリを書き直して、適切な結果を得る方法を次に示します。
WITH max_se_id AS (
SELECT se_id_pf, max(se_id) se_id_max FROM statut_existenta_pf
GROUP BY se_id_pf
)
SELECT p.*, se.se_id_statut, ne.ne_denumire
FROM persoane_fizice p
JOIN statut_existenta_pf se ON se.se_id_pf = p.pf_id
JOIN nom_statut_existenta ne ON ne.id = se.se_id_statut
JOIN max_se_id mse ON se.se_id_pf = mse.se_id_pf
WHERE p.pf_id = :id_pf
AND se.se_id_statut IN
(CASE
WHEN se_data_inceput IS NULL THEN mse.se_id_max
WHEN se_data_inceput IS NOT NULL AND se_data_sfarsit IS NULL THEN mse.se_id_max
ELSE se_id_statut
END) ;
しかし、このクエリは誤った結果をもたらします。指定されたテストベッドでは、se_id
開始時刻が未来であるにもかかわらず、最高のリビジョンが返されます。
データベース内のオブジェクトの履歴を保持するために同じアプローチを使用していますが、代わりにそのようなクエリを使用することをお勧めします。
SELECT p.*, se.se_id_statut, ne.ne_denumire
FROM persoane_fizice p
JOIN statut_existenta_pf se ON se.se_id_pf = p.pf_id
JOIN nom_statut_existenta ne ON ne.id = se.se_id_statut
WHERE p.pf_id = :id_pf
AND statement_timestamp() BETWEEN coalesce(se.se_data_inceput, now())
AND coalesce(se.se_data_sfarsit, clock_timestamp());
se_data_inceput
+se_data_sfarsit
列に重複しない日付がある場合、このクエリは現在アクティブな行を生成します。
私は使用しています:
now()
のデフォルト値としてse_data_inceput
、これは現在のトランザクションの開始時刻をもたらします。
statement_timestamp()
現在の時点として
clock_timestamp()
のデフォルトとしてse_data_sfarsit
。
この組み合わせにより、クエリが履歴テーブルから現在のオブジェクト インスタンスを返すことを常に期待できます。
私の仮定が正しかったことを願っています。