2012-02-13 5 views
0

異なるテキストと他のデータの異なるバージョンをテーブルに保存したい。テキストのために、私のテーブルは次のようになります。私はを照会する方法をまだ知らないPostgreSQLでバージョン管理された行を提供するには良い方法はありますか?それらを照会する方法?

1,0,"My Text, first Version",null 
2,1,"My Text, second Version",1 
3,0,"My 2nd Text v1",null 
4,1,"My 2nd Text v2",3 

id BigSerial, PRIMARY KEY 
version Integer 
text Text 
origin BigInt 

は今、私はこのようなこの表のテキストの異なるバージョンを保存します各行のテキストのバージョン番号が最も高い行。

答えて

1

Bigserial ID番号は有用な目的ではありません。

create temp table my_table (
    id integer not null, 
    version integer not null check(version > 0), 
    -- Give a lot of thought to whether text should also be unique. *I* think 
    -- it probably should, but it's really application-dependent. 
    text Text not null unique, 
    primary key (id, version) 
); 

insert into my_table values 
(1, 1, 'My Text, first Version'), 
(1, 2, 'My Text, second Version'), 
(2, 1, 'My 2nd text v1'), 
(2, 2, 'My 2nd text v2') 

各IDのバージョン数。

select id, count(*) 
from my_table 
group by id; 

各IDの最新バージョン。

with current_ver as (
    select id, max(version) as version 
    from my_table 
    group by id 
) 
select m.* from my_table m 
inner join current_ver c on c.id = m.id and c.version = m.version 

私は共通のテーブル式でこれを書いていましたが、現在のバージョンのビューを作成することをお勧めします。私は、このデータにアクセスするほとんどのアプリケーションが最新のバージョンを必要とすると思います。

+0

賢明な方法を助けるかもしれません。しかし私は自動増分(シリアル)のIDフィールドを逃す - トリガーではそれほど難しくない: CREATE SEQUENCE serial_my_table START 1; NEW.idがnullの場合 \t RETURNSが$$ \t AS \t \tをBEGINトリガ CREATE OR REPLACE FUNCTIONのins_my_table()THEN \t \t \t NEW.id:=のnextval( 'serial_my_table'); \t \t ELSE/*トリガーの後には良いかもしれないが、いくつかのクールなものを行う*/ \t \t END IF; \t \t RETURN NEW; \t END; \t $$言語 'plpgsql'; 存在する場合、ドロップトリガーtr_my_table_ins0 ON my_table; トリガーを作成するtr_my_table_ins0 \t前にmy_tableに挿入 \t各行の実行手順ins_my_table(); – Reinsbrain

1

テキストのすべてが同じレートで新しいバージョンを取得するわけではないので、ID番号と原点の両方を必要としないバージョン番号のアサーションを作成する実際の方法はありません。

たとえば、「5」が特定のテキストセットの最新バージョンであることを知るには、バージョン「6」がないことを確認する必要があります。それを行う方法は、バージョン "5"を持つ行の起点を持つバージョン "6"の行があるかどうかを確認することです。しかし、これはちょうど原点としてそれを主張して他の行を持っていない行を見つけることに減少します。バージョン番号は必要ありません。

したがって、「最高のバージョン番号を持っていますか?」という質問に「自分のIDを起点とする行が他にない」と言い換えることができます。他の行がない場合は、これが最新の行で、結果を返すことができます。あなたは次のクエリのようなもので、これを達成することができます

select t.id 
from table parent 
left join table descendants on parent.id = descendants.origin 
where descendants.id is null; 

をdescendant.idはnullになります結果として結合されたテーブルの行のみが最新なものです。親テーブルと子テーブルの両方が同じテーブルからエイリアスされていることに注意してください。これは「自己結合」と呼ばれ、階層化されたデータ(バージョン管理メカニズムなど)が単一のテーブルに格納されている場合に便利です。

ただし、これは最新のバージョンのみを検出することに注意してください。 を知りたい場合はバージョンですが、これはあなたのバージョンの列を持つことによって間違いなく恩恵を受けるでしょう。さもなければ、バージョンリストの深さを知ることはできないので、再帰クエリを実行する必要はありません。誰もそれらを書くことが好きではありません。

これが役に立ちます。

関連する問題