あなたは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
は(私はinstance_start_date
として、このコラムを扱う)NULL
であれば、その後、与えられた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
列に日付を非オーバーラップしている場合は、このクエリ現在アクティブな行が返されます。私が使用している
:se_data_inceput
のデフォルト値として
now()
を、これは現在のトランザクションの開始時刻を生み出します。 se_data_sfarsit
のデフォルトとして現在時点と
clock_timestamp()
として
statement_timestamp()
。
この組み合わせを使用すると、の現在のオブジェクトインスタンスが履歴テーブルから返されることが常に期待できます。
私の前提が正しいと思います。