2012-11-02 14 views
9

テーブルの列の上位10個の値を更新したいとします。私は3つの列を持っています。 id,accountおよびaccountrank。トップ10の値を取得するには、私は次のように使用することができます。PostgreSQLを使用して上位N個の値を更新する

SELECT * FROM accountrecords  
ORDER BY account DESC 
LIMIT 10; 

は、私は何をしたいのaccountの大きさに基づいて1 - 10一連のことをaccountrankに値を設定することです。これはPostgreSQLで可能ですか?

+2

poatgresのバージョンが8.4以上の場合は、windowing関数+ rank()またはrow_number()を使用できます。 – wildplasser

答えて

22
UPDATE accountrecords a 
SET accountrank = sub.rn 
FROM (
    SELECT id, row_number() OVER (ORDER BY account DESC NULLS LAST) AS rn 
    FROM accountrecords  
    ORDER BY account DESC NULLS LAST 
    LIMIT 10 
    ) sub 
WHERE sub.id = a.id; 

表の結合は、通常、相関サブクエリよりも高速です。それはまた短いです。

window function row_number()とは異なる番号が保証されています。 accountの等しい値を持つ行が同じ番号を共有するようにするには、rank()(場合によってはdense_rank())を使用します。同時書き込みがあることができれば

accountNULL値が存在することができた場合

のみ、あなたは降順のソート順、または上にNULL値のソートにNULLS LASTを追加する必要があります上記のクエリは競合条件の対象となります。考えてみましょう:

それがそうであった場合は、トップ10をハードコーディングの全体のコンセプトは、そもそも怪しげなアプローチになります。

1

確かに、サブクエリでselect文を使用できます。ランクオーダーを生成することは自明ではありませんが、少なくともこれを行う方法は1つあります。私はこれをテストしたが、私の頭の上からされていない:

update accountrecords 
set accountrank = 
    (select count(*) + 1 from accountrecords r where r.account > account) 
where id in (select id from accountrecords order by account desc limit 10); 

これは、2つのレコードがaccountに同じ値を持つ場合、それらは同じランクを取得すること癖を持っています。その特徴を考えることができます:-)

関連する問題