最新のさまざまな usermetadata タグをユーザー行に結合する

StackOverflow https://stackoverflow.com/questions/25224

  •  09-06-2019
  •  | 
  •  

質問

ユーザーテーブル(ユーザーID、名、姓)とユーザーメタデータテーブル(ユーザーID、コード、コンテンツ、作成日時)を備えたpostgresデータベースがあります。各ユーザーに関するさまざまな情報をコードによって usermetadata テーブルに保存し、完全な履歴を保持します。たとえば、ユーザー (ユーザー ID 15) には次のメタデータがあります。

15, 'QHS', '20', '2008-08-24 13:36:33.465567-04'  
15, 'QHE', '8', '2008-08-24 12:07:08.660519-04'  
15, 'QHS', '21', '2008-08-24 09:44:44.39354-04'  
15, 'QHE', '10', '2008-08-24 08:47:57.672058-04'  

すべてのユーザーのリストと、さまざまなユーザーメタデータ コードそれぞれの最新の値を取得する必要があります。私はこれをプログラムで実行しましたが、もちろん恐ろしく遅かったです。SQL でこれを行うために私が考えついた最善の方法は、サブ選択を結合することでしたが、これも時間がかかり、コードごとに 1 つずつ実行する必要がありました。

役に立ちましたか?

解決

あなたはあなたのスキーマを変更したくないと思うので、私のansweはあまり役に立たないかもしれないが、ここに行く...

可能な解決策の1つは、代わりに「廃止予定日」を挿入するときに、新しい値に置き換えられるまで時間フィールドを空にすることです。もう1つの方法は、「アクティブ」列を使用してテーブルを展開することですが、これにより冗長性が導入されます。

古典的な解決策は、他のエントリが有効になるまで「Valid-To」フィールドが空白である「Valid-From」フィールドと「Valid-To」フィールドの両方を使用することです。これは、トリガーなどを使用して簡単に処理できます。制約を使用して、有効な各タイプのアイテムが1つだけであることを確認すると、データの整合性が確保されます。

これらに共通するのは、現在のフィールドのセットを決定する単一の方法があることです。アクティブなユーザーとNULLの「Valid-To」、「deprecation date」、または真の「active」を持つすべてのエントリを選択するだけです。

テンポラルデータベースのWikipediaエントリをご覧になることをお勧めします。記事時間データベースの概念に関するコンセンサス用語集

他のヒント

PostgreSQL には次の機能があるため、これを行うのは実際にはそれほど難しくありません。 「ディスティンクトオン」 SELECT 構文内の句 (DISTINCT ON は標準 SQL ではありません)。

SELECT DISTINCT ON (code) code, content, createtime
FROM metatable
WHERE userid = 15
ORDER BY code, createtime DESC;

これにより、返される結果は一意のコードごとの最初の結果に制限され、結果を作成時間の降順に並べ替えると、それぞれの最新の結果が得られます。

副選択は、この種のことを行う標準的な方法です。 UserId、Code、およびDateに一意の制約が必要なだけで、次を実行できます。

SELECT * 
FROM Table
JOIN (
   SELECT UserId, Code, MAX(Date) as LastDate
   FROM Table
   GROUP BY UserId, Code
) as Latest ON
   Table.UserId = Latest.UserId
   AND Table.Code = Latest.Code
   AND Table.Date = Latest.Date
WHERE
   UserId = @userId
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top