如何在PostgreSQL中進行更新+加入?

本文翻譯自:How to do an update + join in PostgreSQL?

Basically, I want to do this: 基本上,我想這樣做:

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

I'm pretty sure that would work in MySQL (my background), but it doesn't seem to work in postgres. 我很確定這可以在MySQL(我的背景)中使用,但似乎在postgres中不起作用。 The error I get is: 我得到的錯誤是:

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

Surely there's an easy way to do this, but I can't find the proper syntax. 當然,有一種簡單的方法可以執行此操作,但是我找不到正確的語法。 So, how would I write this In PostgreSQL? 那麼,我將如何在PostgreSQL中編寫此代碼?


#1樓

參考:https://stackoom.com/question/X1Eu/如何在PostgreSQL中進行更新-加入


#2樓

Let me explain a little more by my example. 讓我以我的例子作更多解釋。

Task: correct info, where abiturients (students about to leave secondary school) have submitted applications to university earlier, than they got school certificates (yes, they got certificates earlier, than they were issued (by certificate date specified). So, we will increase application submit date to fit certificate issue date. 任務:正確的信息,即那些有進取心的人(即將離開中學的學生)比他們獲得學校證書的時間更早提交申請(是的,他們比得到證書的時間更早(按指定的證書日期)獲得證書。所以,我們將增加申請提交日期以適合證書簽發日期。

Thus. 從而。 next MySQL-like statement: 下一個類似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;

Becomes PostgreSQL-like in such a way 通過這種方式變得像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

As you can see, original subquery JOIN 's ON clause have become one of WHERE conditions, which is conjucted by AND with others, which have been moved from subquery with no changes. 如您所見,原始子查詢JOINON子句已成爲WHERE條件之一,由AND與其他條件結合在一起,這些條件已從子查詢中移出,沒有任何更改。 And there is no more need to JOIN table with itself (as it was in subquery). 並且不再需要將表本身與JOIN (就像在子查詢中一樣)。


#3樓

For those actually wanting to do a JOIN you can also use: 對於真正想要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;

You can use the a_alias in the SET section on the right of the equals sign if needed. 如果需要,可以在等號右側的SET部分中使用a_alias。 The fields on the left of the equals sign don't require a table reference as they are deemed to be from the original "a" table. 等號左側的字段不需要引用表,因爲它們被視爲來自原始的“ a”表。


#4樓

Here we go: 開始了:

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

Simple as I could make it. 我能做到的很簡單。 Thanks guys! 多謝你們!

Can also do this: 也可以這樣做:

-- 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;

But then you've got the vehicle table in there twice, and you're only allowed to alias it once, and you can't use the alias in the "set" portion. 但是隨後您在那兒有兩次車輛表,並且只允許給它別名一次,並且不能在“設置”部分中使用別名。


#5樓

Here's a simple SQL that updates Mid_Name on the Name3 table using the Middle_Name field from Name: 這是一個簡單的SQL,它使用Name中的Middle_Name字段更新Name3表上的Mid_Name:

update name3
set mid_name = name.middle_name
from name
where name3.person_id = name.person_id;

#6樓

The answer of Mark Byers is the optimal in this situation. 在這種情況下,馬克·拜爾斯的答案是最佳的。 Though in more complex situations you can take the select query that returns rowids and calculated values and attach it to the update query like this: 儘管在更復雜的情況下,您可以採用選擇查詢來返回行標識和計算值,並將其附加到更新查詢中,如下所示:

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

This approach lets you develop and test your select query and in two steps convert it to the update query. 這種方法使您可以開發和測試選擇查詢,並在兩個步驟中將其轉換爲更新查詢。

So in your case the result query will be: 因此,在您的情況下,結果查詢將爲:

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

Note that column aliases are mandatory otherwise PostgreSQL will complain about the ambiguity of the column names. 請注意,列別名是必填項,否則PostgreSQL將抱怨列名的歧義。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章