2012-11-02 8 views
9

Ich möchte die Top 10 Werte einer Spalte in der Tabelle aktualisieren. Ich habe drei Spalten; id, account und accountrank. Um den Top-10-Wert erhalten kann ich die folgenden Befehle verwenden:Aktualisieren Sie die oberen N Werte mit PostgreSQL

SELECT * FROM accountrecords  
ORDER BY account DESC 
LIMIT 10; 

Was würde Ich mag zu tun ist, um den Wert in accountrank setzt eine Reihe von 1 - 10 zu sein, basierend auf der Größe von account. Ist das in PostgreSQL möglich?

+2

Wenn Ihre Poatgres-Version 8.4 oder höher ist, können Sie die Windowing-Funktionen + rank() oder row_number() verwenden. – wildplasser

Antwort

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; 

Join in einer Tabelle ist in der Regel schneller als korrelierte Unterabfragen. Es ist auch kürzer.

Mit der window function row_number() sind eindeutige Nummern garantiert. Verwenden Sie rank() (oder möglicherweise dense_rank()), wenn Sie möchten, dass Zeilen mit gleichen Werten für account die gleiche Nummer verwenden.

Nur wenn es NULL Werte in account sein können, müssen Sie NULLS LAST für absteigende Sortierreihenfolge anzuhängen oder NULL Werte sortieren oben:

Wenn kann es gleichzeitige Schreib Zugriff, die obige Abfrage unterliegt einer Race-Bedingung. Bedenken Sie:

Wenn dies jedoch der Fall ist, das gesamte Konzept der Hartcodierung des Top Ten wäre ein zweifelhafter Ansatz zu beginnen.

1

Sicher können Sie Ihre SELECT-Anweisung in einer Unterabfrage verwenden. Die Rangordnung zu erzeugen ist nicht trivial, aber hier ist mindestens eine Möglichkeit, dies zu tun. Ich habe nicht getestet, aber aus der Spitze von meinem Kopf:

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); 

Dies hat die Marotte, dass, wenn zwei Datensätze den gleichen Wert für account haben, dann werden sie den gleichen Rang erhalten. Sie könnten dies als ein Feature betrachten ... :-)

Verwandte Themen