4

user テーブル (userid、firstname、lastname) と usermetadata テーブル (userid、code、content、created datetime) を持つ postgres データベースがあります。各ユーザーに関するさまざまな情報をコードで usermetadata テーブルに保存し、完全な履歴を保持します。たとえば、ユーザー (userid 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 つ実行する必要がありました。

4

3 に答える 3

6

PostgreSQLでは、SELECT 構文に"DISTINCT ON"句があるため (DISTINCT ON は標準 SQL ではありません)、これは実際にはそれほど難しくありません。

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

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

于 2008-08-26T00:29:36.100 に答える
1

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

考えられる解決策の 1 つは、代わりに「非推奨日」を挿入するときに、新しい値に置き換えられるまで時間フィールドを空にすることです。もう 1 つの方法は、「アクティブな」列を使用してテーブルを拡張することですが、冗長性が生じます。

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

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

テンポラル データベースに関するウィキペディアのエントリと、テンポラル データベースの概念に関するコンセンサス用語集に関する記事を参照してください。

于 2008-08-24T18:11:02.603 に答える
0

副選択は、この種のことを行う標準的な方法です。UserId、Code、および Date に Unique Constraint が必要なだけで、次のコマンドを実行できます。

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
于 2008-08-27T14:42:34.247 に答える