inner - update from select postgresql
¿Cómo hacer una actualización+unirse a PostgreSQL? (6)
Aquí hay un SQL simple que actualiza Mid_Name en la tabla de Name3 usando el campo Middle_Name de Name:
update name3
set mid_name = name.middle_name
from name
where name3.person_id = name.person_id;
Básicamente, quiero hacer esto:
update vehicles_vehicle v
join shipments_shipment s on v.shipment_id=s.id
set v.price=s.price_per_vehicle;
Estoy bastante seguro de que funcionaría en MySQL (mi fondo), pero parece que no funciona en postgres. El error que recibo es:
ERROR: syntax error at or near "join"
LINE 1: update vehicles_vehicle v join shipments_shipment s on v.shi...
^
Seguramente hay una forma fácil de hacer esto, pero no puedo encontrar la sintaxis correcta. Entonces, ¿cómo escribiría esto en PostgreSQL?
Aquí vamos:
update vehicles_vehicle v
set price=s.price_per_vehicle
from shipments_shipment s
where v.shipment_id=s.id;
Tan simple como pude hacerlo. ¡Gracias chicos!
También puede hacer esto:
update vehicles_vehicle
set price=s.price_per_vehicle
from vehicles_vehicle v
join shipments_shipment s on v.shipment_id=s.id;
Pero luego tienes la tabla de vehículos allí dos veces, y solo puedes aliasla una vez, y no puedes usar el alias en la parte "conjunto".
Déjame explicarte un poco más con mi ejemplo.
Tarea: información correcta, donde los abiturientes (estudiantes que están a punto de abandonar la escuela secundaria) han presentado solicitudes a la universidad antes de que obtuvieran los certificados escolares (sí, obtuvieron los certificados antes de lo que fueron emitidos (por fecha de certificado especificada). aumentar la fecha de envío de la solicitud para que se ajuste a la fecha de emisión del certificado.
Así. siguiente declaración de MySQL:
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;
Se convierte en similar a PostgreSQL de tal manera
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
Como puede ver, la cláusula ON
subconsulta original se ha convertido en una de las condiciones WHERE
, que se conjuga con AND
con otras, que se han trasladado de la subconsulta sin cambios. Y ya no hay necesidad de JOIN
tabla consigo misma (como estaba en la subconsulta).
La sintaxis de UPDATE es:
[ WITH [ RECURSIVE ] with_query [, ...] ] UPDATE [ ONLY ] table [ [ AS ] alias ] SET { column = { expression | DEFAULT } | ( column [, ...] ) = ( { expression | DEFAULT } [, ...] ) } [, ...] [ FROM from_list ] [ WHERE condition | WHERE CURRENT OF cursor_name ] [ RETURNING * | output_expression [ [ AS ] output_name ] [, ...] ]
En tu caso creo que quieres esto:
UPDATE vehicles_vehicle AS v
SET price = s.price_per_vehicle
FROM shipments_shipment AS s
WHERE v.shipment_id = s.id
La respuesta de Mark Byers es la óptima en esta situación. Aunque en situaciones más complejas, puede tomar la consulta de selección que devuelve filas y valores calculados y adjuntarla a la consulta de actualización de esta manera:
with t as (
-- Any generic query which returns rowid and corresponding calculated values
select t1.id as rowid, f(t2, t2) as calculatedvalue
from table1 as t1
join table2 as t2 on t2.referenceid = t1.id
)
update t1
set value = t.calculatedvalue
from t
where id = t.rowid
Este enfoque le permite desarrollar y probar su consulta de selección y, en dos pasos, convertirla en la consulta de actualización.
Así que en tu caso la consulta de resultados será:
with t as (
select v.id as rowid, s.price_per_vehicle as calculatedvalue
from vehicles_vehicle v
join shipments_shipment s on v.shipment_id = s.id
)
update vehicles_vehicle
set price = t.calculatedvalue
from t
where id = t.rowid
Tenga en cuenta que los alias de columna son obligatorios, de lo contrario, PostgreSQL se quejará de la ambigüedad de los nombres de columna.
Para aquellos que realmente quieran hacer una JOIN
también puedes usar:
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'' AND a.id = a_alias.id;
Puede usar a_alias en la sección SET
a la derecha del signo igual si es necesario. Los campos a la izquierda del signo igual no requieren una referencia de tabla, ya que se considera que son de la tabla "a" original.