Sql 使用内部查询(联接)更新

Sql 使用内部查询(联接)更新,sql,postgresql,Sql,Postgresql,我想我正在失去它,谁能解释我为什么会经历以下情况: 我的问题是: 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.o

我想我正在失去它,谁能解释我为什么会经历以下情况: 我的问题是:

    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_表上执行,并每天更新所有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,连接条件并没有保留,它是包含的,应该只为更新呈现匹配的行。因此,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。 显然,我对连接使用了一个错误的假设,我的背景是MS-SQL,它在那里的工作方式不同。 从最终解决方案来看,连接被完全删除,并通过直接调用辅助表进行交换,这在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;
  • 这种复杂的联接是由于我试图确保内部查询只返回整个表的一个子集以进行“调试”而导致的

再次感谢

您的更新没有
WHERE
条件

此语句将更新所有行

您的声明可能是这样的(简化得多):


您没有一个链接到表的
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

感谢您的快速回答,请参阅编辑后的问题,自使用JOIN后,where条件不应成为问题。感谢您的简化,我们将实施它@卡夫先生:加入并不像你认为的那样。它只连接FROM子句中的两个表。也许你已经习惯了MySQL扭曲的更新语法?您仍然需要WHERE子句。我加了一句话——猜测这可能是你真正想要的。再次简化。谢谢埃尔文,现在它开始工作了,但说实话,我仍然不知道为什么会发生这种情况。我添加了另一个我尝试使用的查询,它在where中强制执行id=id检查,但没有得到好的结果。您的解决方案有效,我将从现在开始使用这种方法,但我不确定哪一种是twisted db:)@mr.kav:从阅读以下内容开始。它的工作原理与tSQL或MySQL不同。PostgreSQL的
FROM
子句是对SQL标准的扩展,但在我看来更简单、更直截了当。正如您所看到的,生成的语句更短、更容易阅读。感谢您的快速回答,请参阅编辑后的问题,自从使用JOIN后,where条件不应成为问题。这正是您遇到的问题,因为FROM之后的查询部分现在与FROM之前的部分没有任何关系。引用要更新的同一个表并不意味着它与update语句相关。事实并非如此。
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