831 votes

Comment faire une mise à jour + se joindre à PostgreSQL?

Fondamentalement, je veux faire ceci:

 update vehicles_vehicle v 
    join shipments_shipment s on v.shipment_id=s.id 
set v.price=s.price_per_vehicle;
 

Je suis sûr que cela fonctionnerait dans MySQL (mon arrière-plan), mais cela ne semble pas fonctionner dans postgres. L'erreur que je reçois est:

 ERROR:  syntax error at or near "join"
LINE 1: update vehicles_vehicle v join shipments_shipment s on v.shi...
                                  ^
 

Il y a sûrement un moyen facile de le faire, mais je ne trouve pas la syntaxe appropriée. Alors, comment est-ce que j'écrirais ceci dans PostgreSQL?

1214voto

Mark Byers Points 318575

La mise à JOUR de la syntaxe est:

[[ RECURSIVE ] with_query [, ...] ]
Mise à JOUR [ SEULEMENT ] de la table [ [ COMME ] alias ]
 SET { column = { expression | DEFAULT } |
 ( colonne [, ...] ) = ( { expression | par DÉFAUT } [, ...] ) } [, ...]
 [ À PARTIR de from_list ]
 [ Where condition | OÙ DE cursor_name ]
 [ RETOUR * | output_expression [ [ COMME ] nom_sortie ] [, ...] ]

Dans votre cas, je pense que vous voulez ce:

UPDATE vehicles_vehicle AS v 
SET price = s.price_per_vehicle
FROM shipments_shipment AS s
WHERE v.shipment_id = s.id 

195voto

Envek Points 444

Laissez-moi vous expliquer un peu plus par mon exemple.

Tâche: corriger info, où abiturients ont soumis des demandes à l'université plus tôt, qu'ils ont obtenu des certificats de scolarité (oui, ils ont obtenu les certificats antérieurs, qu'ils ont été émis (par certificat date indiquée). Donc, nous allons augmenter la demande date de soumettre à l'ajustement du certificat à la date d'émission.

Ainsi. prochaine MySQL-comme la déclaration:

UPDATE applications a
JOIN (
    SELECT ap.id, ab.certificate_issued_at
    FROM abiturients ab
    JOIN applications ap 
    ON ab.id = ap.abiturient_id 
    WHERE ap.documents_taken_at::date < ab.certificate_issued_at
) b
ON a.id = b.id
SET a.documents_taken_at = b.certificate_issued_at;

Devient PostgreSQL-comme dans la manière

UPDATE applications a
SET documents_taken_at = b.certificate_issued_at         -- we can reference joined table here
FROM abiturients b                                       -- joined table
WHERE 
    a.abiturient_id = b.id AND                           -- JOIN ON clause
    a.documents_taken_at::date < b.certificate_issued_at -- Subquery WHERE

Comme vous pouvez le voir, originale sous-requête JOINs' ON clause est devenue l'une des WHERE conditions, ce qui est conjucted en AND avec d'autres, qui ont été déplacés à partir de la sous-requête sans aucune modification. Et il n'y a pas besoin de plus de JOIN table avec elle-même (comme il l'a été dans la sous-requête).

156voto

Fast Engy Points 157

Pour ceux qui veulent faire une jointure, vous pouvez aussi utiliser:

 UPDATE a
SET price = b_alias.unit_price
FROM a as a_alias
LEFT JOIN b as b_alias ON a_alias.b_fk = b_alias.id
WHERE a_alias.unit_name LIKE 'some_value';
 

Vous pouvez utiliser a_alias dans la section SET à droite du signe égal si nécessaire. Les champs situés à gauche du signe égal ne requièrent pas de référence de table car ils sont réputés provenir de la table "a" d'origine.

11voto

Mark Points 49079

Et c'est parti:

 update vehicles_vehicle v
set price=s.price_per_vehicle
from shipments_shipment s
where v.shipment_id=s.id;
 

Simple comme je pourrais le faire. Merci les gars!

Peut aussi faire ceci:

 update vehicles_vehicle 
set price=s.price_per_vehicle
from vehicles_vehicle v
join shipments_shipment s on v.shipment_id=s.id;
 

Mais alors vous avez deux fois la table du véhicule, et vous n'êtes autorisé à l'alias qu'une seule fois, et vous ne pouvez pas utiliser l'alias dans la partie "set".

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X