1 番目のテーブルの有効な行に基づいて、2 番目のテーブルで最後/最新の更新を取得するために結合する必要がある 2 つのテーブルがあります。
以下のコードは例です。
表 1: 登録済みユーザー
この表には、システムに登録されているユーザーのリストが含まれています。ユーザーが登録されると、このテーブルに追加されます。ユーザーは、名前と登録時刻で登録されます。ユーザーはシステムから登録解除できます。これが完了すると、登録解除列は、ユーザーが削除された時刻に更新されます。この値が NULL の場合、ユーザーがまだ登録されていることを意味します。
CREATE TABLE users (
entry_idx SERIAL PRIMARY KEY,
name TEXT NOT NULL,
reg_time TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
dereg_time TIMESTAMP WITH TIME ZONE DEFAULT NULL
);
表 2: ユーザーの更新
この表には、ユーザーに関する更新が含まれています。ユーザーがプロパティ (位置の例) を変更するたびに、変更がこのテーブルに保存されます。テーブルに履歴を保持する必要があるため、更新を削除する必要はありません。
CREATE TABLE user_updates (
entry_idx SERIAL PRIMARY KEY,
name TEXT NOT NULL,
position INTEGER NOT NULL,
time TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
必要な出力
したがって、上記の情報を考慮して、現在の登録ユーザーの最終更新のみを含む新しいテーブルを取得する必要があります。
テスト データ
次のデータは、上記の表のテスト データとして使用できます。
-- Register 3 users
INSERT INTO users(name) VALUES ('Person1');
INSERT INTO users(name) VALUES ('Person2');
INSERT INTO users(name) VALUES ('Person3');
-- Add some updates for all users
INSERT INTO user_updates(name, position) VALUES ('Person1', 0);
INSERT INTO user_updates(name, position) VALUES ('Person1', 1);
INSERT INTO user_updates(name, position) VALUES ('Person1', 2);
INSERT INTO user_updates(name, position) VALUES ('Person2', 1);
INSERT INTO user_updates(name, position) VALUES ('Person3', 1);
-- Unregister the 2nd user
UPDATE users SET dereg_time = NOW() WHERE name = 'Person2';
以上から、人物1と人物3の最新情報が欲しいです。
試行の失敗
結合やその他の方法を使用してみましたが、探している結果が得られません。ここでの質問とほぼ同じです。回答1のソリューションを使用しましたが、正しい回答が得られますが、システムで回答を得るのに時間がかかりすぎます。
上記のリンクに基づいて、「機能する」次のクエリを作成しました。
SELECT
t1.*
, t2.*
FROM
users t1
JOIN (
SELECT
t.*,
row_number()
OVER (
PARTITION BY
t.name
ORDER BY t.entry_idx DESC
) rn
FROM user_updates t
) t2
ON
t1.name = t2.name
AND
t2.rn = 1
WHERE
t1.dereg_time IS NULL;
問題 上記のクエリの問題は、完了するまでに非常に時間がかかることです。表 1 にはユーザーの小さなリストが含まれていますが、表 2 には大量の更新が含まれています。2つのテーブルを処理する方法で、クエリが非効率的である可能性があると思います(クエリに対する私の限られた理解に基づいて)。pgAdminの説明から、登録されたテーブルに参加する前に、最初に更新に対して多くの並べ替えと集計を行います。
質問
登録ユーザーの最新の更新を効率的かつ迅速に取得するためのクエリを作成するにはどうすればよいですか?