2012-11-02 16 views
9

Desidero aggiornare i primi 10 valori di una colonna nella tabella. Ho tre colonne; id, account e accountrank. Per ottenere i primi 10 valori posso utilizzare il seguente:Aggiornamento dei valori N migliori con PostgreSQL

SELECT * FROM accountrecords  
ORDER BY account DESC 
LIMIT 10; 

Quello che vorrei fare è impostare il valore in accountrank ad essere una serie di 1 - 10, in base alla grandezza della account. È possibile farlo in PostgreSQL?

+2

Se la versione di Poatgres è 8.4 o successiva, è possibile utilizzare le funzioni di windowing + rank() o row_number(). – wildplasser

risposta

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; 

L'unione in una tabella è in genere più veloce delle sottoquery correlate. È anche più breve.

Con i numeri distinti window function row_number() sono garantiti. Utilizzare rank() (o eventualmente dense_rank()) se si desidera che righe con valori uguali per account condividano lo stesso numero.

Solo se ci possono essere NULL valori in account, è necessario aggiungere NULLS LAST per decrescente ordinamento, o NULL valori sorta in alto:

Se non ci può essere scrittura simultanea accesso, la query di cui sopra è soggetta a una condizione di gara . Considerate:

Tuttavia, se questo era il caso, l'intero concetto di codificare la top ten sarebbe un approccio discutibile per cominciare.

1

Certo, puoi usare la tua istruzione select in una sottoquery. Generare il rango non è banale, ma ecco almeno un modo per farlo. Non ho ancora testato questo, ma la parte superiore della mia testa:

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

Questo ha il vezzo che se due record hanno lo stesso valore per account, allora otterranno lo stesso rango. Potresti considerare una funzionalità ... :-)

Problemi correlati