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 条记录,但更新是在整个财务表中执行的。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
);

编辑:
感谢您的快速回答,但是不应该需要 where,连接条件不是 LEFT,它是包容性的,并且应该只呈现匹配的行以进行更新。因此,应更新 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;
  • 复杂的连接是我试图确保内部查询仅返回整个表的子集以用于“调试”目的的结果。

再次感谢!

4

2 回答 2

1

您的 UPDATE没有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?
于 2012-04-11T15:23:31.570 回答
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
于 2012-04-11T15:24:34.267 回答