2010-12-05 15 views
19

J'ai une grande table PostgreSQL à laquelle j'accède via Django. Étant donné que l'ORM de Django ne prend pas en charge les fonctions de fenêtre, j'ai besoin de faire cuire les résultats d'une fonction de fenêtre dans la table en tant que colonne régulière. Je veux faire quelque chose comme ceci:Utilisation des fonctions de fenêtre dans une instruction de mise à jour

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

Mais je reçois ERROR: cannot use window function in UPDATE

Quelqu'un peut-il proposer une autre approche? Passer la syntaxe de la fonction fenêtre via la méthode .raw() de Django ne convient pas, car elle retourne un RawQuerySet, qui ne supporte pas d'autres fonctionnalités ORM telles que .filter(), dont j'ai besoin.

Merci.

Répondre

34

L'erreur provient de postgres et non de django. Vous pouvez réécrire ce que:

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; 

Ou bien:

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; 

Cela fonctionne. Juste testé sur postgres-9.6. Voici la syntaxe pour UPDATE (voir l'option de la liste).

Espérons que cela aide.

+0

Je ne pense pas que vous ayez besoin de l'auto-jointure? Je pourrais bien me tromper alors que je me base sur ce qui fonctionne dans SQL Server! –

+0

@Martin: Vous sélectionnez deux tables, l'une est UPDATE 'tablename' et l'autre est dans la clause' FROM tablename'. Si vous ne vous joignez pas explicitement, cela va produire un produit cartésien. – Max

+0

euh, non je ne suis pas! –