2010-12-05 4 views
19

Ich habe eine große PostgreSQL-Tabelle, die ich über Django zugreifen. Da Djangos ORM keine Fensterfunktionen unterstützt, muss ich die Ergebnisse einer Fensterfunktion als reguläre Spalte in die Tabelle einbinden. Ich möchte so etwas wie dies zu tun:Verwenden von Fensterfunktionen in einer Update-Anweisung

UPDATE table_name 
SET  col1 = ROW_NUMBER() OVER (PARTITION BY col2 ORDER BY col3); 

Aber ich bekomme ERROR: cannot use window function in UPDATE

Kann jemand einen alternativen Ansatz vorschlagen? Das Übergeben der Window-Funktionssyntax über Djangos .raw() -Methode ist nicht geeignet, da sie ein RawQuerySet zurückgibt, das keine weiteren ORM-Features wie .filter() unterstützt, die ich brauche.

Danke.

Antwort

34

Der Fehler ist von Postgres nicht Django. Sie können umschreiben dies als:

WITH v_table_name AS 
(
    SELECT row_number() over (partition by col2 order by col3) AS rn, primary_key 
    FROM table_name 
) 
UPDATE table_name set table_name.col1 = v_table_name.rn 
FROM v_table_name 
WHERE table_name.primary_key = v_table_name.primary_key; 

Oder alternativ:

UPDATE table_name set table_name.col1 = v_table_name.rn 
FROM 
(
    SELECT row_number() over (partition by col2 order by col3) AS rn, primary_key 
    FROM table_name 
) AS v_table_name 
WHERE table_name.primary_key = v_table_name.primary_key; 

Dies funktioniert. Habe es gerade auf Postgres-9.6 getestet. Hier ist die Syntax für UPDATE (siehe die optionale fromlist).

Hoffe, das hilft.

+0

Ich glaube nicht, dass Sie das selbst beitreten müssen? Ich könnte aber auch falsch liegen, da ich dies auf das aufbaue, was in SQL Server funktioniert! –

+0

@Martin: Sie wählen zwei Tabelle aus, eine durch UPDATE 'Tabellenname' und eine andere in der' FROM Tabellenname'-Klausel. Wenn Sie nicht explizit beitreten, entsteht ein kartesisches Produkt. – Max

+0

äh, Nein, ich bin nicht! –