[postgresql] PostgreSQL에서 업데이트 + 가입을 수행하는 방법은 무엇입니까?
기본적으로 나는 이것을하고 싶다 :
update vehicles_vehicle v
join shipments_shipment s on v.shipment_id=s.id
set v.price=s.price_per_vehicle;
나는 그것이 MySQL (내 배경)에서 작동 할 것이라고 확신하지만 postgres에서는 작동하지 않는 것 같습니다. 내가 얻는 오류는 다음과 같습니다.
ERROR: syntax error at or near "join"
LINE 1: update vehicles_vehicle v join shipments_shipment s on v.shi...
^
분명히이 작업을 수행하는 쉬운 방법이 있지만 올바른 구문을 찾을 수 없습니다. PostgreSQL에서 어떻게 작성합니까?
답변
UPDATE 구문 입니다 :
[WITH [RECURSIVE] with_query [, ...]] UPDATE [ONLY] 테이블 [[AS] alias] SET {column = {표현식 | 기본} | (column [, ...]) = ({expression | DEFAULT} [, ...])} [, ...] [FROM from_list] [여기서 조건 | cursor_name의 현재 위치] [반품 * | output_expression [[AS] output_name] [, ...]]
귀하의 경우에 나는 당신이 이것을 원한다고 생각합니다 :
UPDATE vehicles_vehicle AS v
SET price = s.price_per_vehicle
FROM shipments_shipment AS s
WHERE v.shipment_id = s.id
답변
예를 들어 조금 더 설명하겠습니다.
과제 : 모든 정보 (중등 학교를 떠나려는 학생)가 학교 증명서를받은 것보다 일찍 대학에 신청서를 제출 한 올바른 정보 (예, 증명서를받은 것보다 발급 된 것보다 일찍 (인증서가 지정된 날짜)) 인증서 발급 날짜에 맞게 신청서 제출 날짜를 늘리십시오.
그러므로. 다음 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;
그런 식으로 PostgreSQL과 같이됩니다.
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
보시다시피, 원래 하위 쿼리 JOIN
의 ON
절은 다른 쿼리와 함께 사용 WHERE
되는 조건 중 하나 AND
가되었으며 변경없이 하위 쿼리에서 이동되었습니다. 그리고 JOIN
하위 쿼리에서와 같이 더 이상 자체적 으로 테이블을 지정할 필요가 없습니다 .
답변
이 상황에서 Mark Byers의 답변이 최적입니다. 더 복잡한 상황에서는 rowid와 계산 된 값을 반환하는 select 쿼리를 사용하여 다음과 같이 업데이트 쿼리에 연결할 수 있습니다.
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 table1
set value = t.calculatedvalue
from t
where id = t.rowid
이 방법을 사용하면 선택 쿼리를 개발 및 테스트 할 수 있으며 두 단계로이를 업데이트 쿼리로 변환 할 수 있습니다.
따라서 귀하의 경우 결과 쿼리는 다음과 같습니다.
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
열 별칭은 필수 사항입니다. 그렇지 않으면 PostgreSQL은 열 이름의 모호성에 대해 불평합니다.
답변
실제로하고 싶은 사람들을 위해 다음 JOIN
을 사용할 수도 있습니다.
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;
SET
필요한 경우 등호 오른쪽의 섹션에서 a_alias를 사용할 수 있습니다 . 등호 왼쪽에있는 필드는 원래 “a”테이블에서 온 것으로 간주되므로 테이블 참조가 필요하지 않습니다.
답변
조인이 반환하는 행만 업데이트하는 JOIN을 수행하려는 경우 다음을 사용하십시오.
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
--the below line is critical for updating ONLY joined rows
AND a.pk_id = a_alias.pk_id;
이것은 위에서 언급되었지만 의견을 통해서만 언급되었습니다. 정확한 결과를 게시하는 것이 중요하기 때문에 작동합니다.
답변
여기 우리는 간다 :
update vehicles_vehicle v
set price=s.price_per_vehicle
from shipments_shipment s
where v.shipment_id=s.id;
내가 할 수있는 것처럼 간단합니다. 고마워요!
또한 이것을 할 수 있습니다 :
-- Doesn't work apparently
update vehicles_vehicle
set price=s.price_per_vehicle
from vehicles_vehicle v
join shipments_shipment s on v.shipment_id=s.id;
그러나 비히클 테이블이 두 번 있고, 한 번만 별칭을 사용할 수 있으며 “set”부분에 별칭을 사용할 수 없습니다.
답변
다음은 Name의 Middle_Name 필드를 사용하여 Name3 테이블에서 Mid_Name을 업데이트하는 간단한 SQL입니다.
update name3
set mid_name = name.middle_name
from name
where name3.person_id = name.person_id;