テーブルの列の上位10個の値を更新したいと思います。私には3つの列があります。id
、account
およびaccountrank
。上位10の値を取得するには、次を使用できます。
SELECT * FROM accountrecords
ORDER BY account DESC
LIMIT 10;
私がやりたいのは、の大きさに基づいて、の値をaccountrank
一連のに設定することです。これはPostgreSQLで実行できますか?1 - 10
account
テーブルの列の上位10個の値を更新したいと思います。私には3つの列があります。id
、account
およびaccountrank
。上位10の値を取得するには、次を使用できます。
SELECT * FROM accountrecords
ORDER BY account DESC
LIMIT 10;
私がやりたいのは、の大きさに基づいて、の値をaccountrank
一連のに設定することです。これはPostgreSQLで実行できますか?1 - 10
account
WITH cte AS (
SELECT id, row_number() OVER (ORDER BY account DESC NULLS LAST) AS rn
FROM accountrecords
ORDER BY account DESC NULLS LAST
LIMIT 10
)
UPDATE accountrecords a
SET accountrank = cte.rn
FROM cte
WHERE cte.id = a.id;
テーブル式への結合は、通常、相関サブクエリよりも高速です。また短いです。
ウィンドウ関数row_number()
を使用すると、個別の番号が保証されます。の値が等しい行で同じ数を共有する場合は、 rank()
(または場合によっては)を使用します。dense_rank()
account
NULL
に値を含めることができる場合にのみ、降順で並べ替えるためaccount
に追加するか、値を上に並べ替える必要があります。NULLS LAST
NULL
同時書き込みアクセスが可能な場合、上記のクエリは競合状態の影響を受けます。検討:
ただし、その場合、トップ10をハードコーディングするという概念全体は、そもそも疑わしいアプローチになります。
LIMIT
信頼性の高い方法を適用するには、(最初に使用したような)単純なサブクエリの代わりにCTEを使用します。上記のリンクを参照してください。
もちろん、サブクエリで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);
account
これには、2つのレコードの値が同じである場合、それらが同じランクになるという癖があります。あなたはその機能を考えることができます...:-)