2012-04-11 104 views
0

我覺得我失去了它,任何人都可以解釋爲什麼我會遇到以下: 這裏是我的查詢:更新(加入)

update financials.operator_summary_daily set 
     osm_fos_id = fos_id 
    from financials.operator_summary_daily daily 
    join (
     select 
      osm_id, 
      fos_id 
     from financials.operator_summary_daily daily 
     join financials.operator_settlement_monthly on daily.osm_opt_id = fos_opt_id and date_trunc('month', daily.osm_timestamp)::timestamp = date_trunc('month', fos_timestamp)::timestamp --and daily.osm_fos_id is null 
    ) as result on result.osm_id = daily.osm_id 

內查詢返回1963條記錄,但更新在financials.operator_summary_daily的整個表上執行並更新所有39K記錄。

我在這裏錯過了什麼?

表:

CREATE TABLE financials.operator_summary_daily 
(
    osm_id bigint NOT NULL DEFAULT nextval('financials.operator_summary_monthly_osm_id_seq'::regclass), 
    osm_timestamp timestamp without time zone NOT NULL, 
    osm_opt_id bigint NOT NULL, 
    osm_gam_id bigint NOT NULL, 
    osm_cur_id bigint NOT NULL, 
    osm_ctt_id bigint NOT NULL, 
    osm_turnover double precision NOT NULL, 
    osm_revenue double precision NOT NULL, 
    osm_timestamp_created timestamp without time zone NOT NULL DEFAULT now(), 
    osm_timestamp_updated timestamp without time zone NOT NULL DEFAULT ('now'::text)::date, 
    osm_fos_id bigint 
); 


CREATE TABLE financials.operator_settlement_monthly 
(
    fos_id bigserial NOT NULL, 
    fos_timestamp timestamp without time zone NOT NULL, -- Monthly timestamp 
    fos_opt_id bigint NOT NULL, 
    fos_royalties double precision NOT NULL, 
    fos_carry_over double precision NOT NULL, 
    fos_other_adjustments double precision NOT NULL, 
    fos_due double precision NOT NULL, 
    fos_collectable double precision NOT NULL, 
    fos_balance double precision NOT NULL, 
    fos_collected double precision NOT NULL, 
    fos_baddebt double precision NOT NULL, 
    fos_carryforward double precision NOT NULL, 
    fos_ses_id bigint NOT NULL, 
    fos_timestamp_created timestamp without time zone NOT NULL DEFAULT now(), 
    fos_datetime_updated timestamp without time zone NOT NULL DEFAULT now(), 
    fos_prq_id bigint 
); 

編輯:
謝謝你的快速解答,但不應該有需要的地方,連接條件不剩,這是包容性的,只有應該呈現匹配行進行更新。因此,應該更新37K(符合加入標準的那些)中的1963個記錄。我錯了嗎?

答: 正確的腳本:

UPDATE financials.operator_summary_daily d 
    SET osm_fos_id = m.fos_id 
    FROM financials.operator_settlement_monthly m 
    WHERE 
     m.fos_opt_id = d.osm_opt_id 
     AND date_trunc('month', d.osm_timestamp) = date_trunc('month', m.fos_timestamp) 
     AND d.osm_fos_id is null; 

謝謝@ErwinBrandstetter。 顯然,我一直在使用JOIN的一個錯誤的假設,我的背景是MS-SQL,它在那裏的工作方式不同。 從查看最終解決方案看,JOIN完全被刪除,並直接調用輔助表進行交換,這在T-SQL中是無法做到的。

順便說一句,以下不起作用,它包含一個where子句作爲其他意見建議。我仍然不明白pgsql在更新記錄時如何處理JOIN。

update financials.operator_summary_daily set 
     osm_fos_id = fos_id 
    from financials.operator_summary_daily daily 
    join (
     select 
      osm_id, 
      fos_id 
     from financials.operator_summary_daily daily 
     join financials.operator_settlement_monthly on daily.osm_opt_id = fos_opt_id and date_trunc('month', daily.osm_timestamp)::timestamp = date_trunc('month', fos_timestamp)::timestamp 
    ) as result on result.osm_id = daily.osm_id 
    where 
     daily.osm_id = result.osm_id 
     and daily.osm_fos_id is null; 
  • 這個複雜的連接是我的努力確保內部查詢只返回整個表的子集「調試」宗旨的結果。

再次感謝!

回答

1

沒有WHERE條件到您的更新。

此聲明將更新all行。

你的語句可能像這樣工作(大大簡化):

UPDATE financials.operator_summary_daily d 
SET osm_fos_id = m.fos_id 
FROM financials.operator_settlement_monthly m 
WHERE m.fos_opt_id = d.osm_opt_id 
AND date_trunc('month', d.osm_timestamp) = date_trunc('month', m.fos_timestamp) 
-- AND daily.osm_fos_id is null -- ?? Why is this here/commented out? 
+0

感謝您的快速回答,請參閱編輯的問題,應該不是因爲使用JOIN條件的問題。並感謝您的簡化,實施它! – itayw 2012-04-11 15:28:46

+0

@ mr.kav:JOIN不符合您的想法。它只加入FROM子句中的兩個表。也許你習慣於MySQL的扭曲UPDATE語法?你仍然需要一個WHERE子句。我添加了一個聲明 - 猜測這可能是你真正想要的。再簡化一次。 – 2012-04-11 15:32:12

+0

謝謝Erwin,現在就開始工作了,但說實話,我仍然不知道爲什麼會發生這種情況。我添加了另一個我嘗試使用的查詢,它強制執行id = id檢查哪裏,沒有好的結果。你的解決方案的工作原理,我將從現在開始使用這種方法,但我不確定哪個是扭曲的db :) – itayw 2012-04-11 15:46:55

0

你沒有WHERE條款鏈接到表,查詢後FROM

更新到結果你需要做一些像

update financials.operator_summary_daily set 
    osm_fos_id = fos_id 
from financials.operator_summary_daily daily 
join (
    select 
     osm_id, 
     fos_id 
    from financials.operator_summary_daily daily 
    join financials.operator_settlement_monthly on daily.osm_opt_id = fos_opt_id and date_trunc('month', daily.osm_timestamp)::timestamp = date_trunc('month', fos_timestamp)::timestamp --and daily.osm_fos_id is null 
) as result on result.osm_id = daily.osm_id 
WHERE daily.osm_id = financials.operator_summary_daily.osm_id -- condition to link 
+0

感謝您的快速回答,請參閱編輯的問題,不應該因爲使用JOIN而引起問題。 – itayw 2012-04-11 15:29:00

+1

這是確實存在的問題,因爲* FROM之後的查詢*部分現在與* FROM之前的部分無關。事實上,你引用的同一張表你想更新並不意味着它與更新語句有關。不是這樣。 – 2012-04-11 15:33:35