Postgres - 使用join进行更新会产生错误的结果

时间:2017-04-17 16:58:21

标签: postgresql join where

我很难理解我做错了什么。 此查询的结果显示每行的结果相同,而不是由正确的结果更新。

我的数据

我正在尝试更新一组业务的统计信息表

business_stats ( id SERIAL,
                 pk integer not null,
                 b_total integer,
                 PRIMARY KEY(pk)
                );

每个商家的详细信息都存储在这里

business_details (id SERIAL,
                  category CHARACTER VARYING,
                  feature_a CHARACTER VARYING,
                  feature_b CHARACTER VARYING,
                  feature_c CHARACTER VARYING
                  );

这里有一个将 pk 类别相关联的表

datasets (id SERIAL,
          pk integer not null,
          category CHARACTER VARYING;
          PRIMARY KEY(pk)
          );

我做了什么(错误)

UPDATE business_stats
SET b_total = agg.total
FROM business_stats b,
     (  SELECT  d.pk, count(bd.id) total
        FROM business_details AS bd
            INNER JOIN datasets AS d
            ON bd.category = d.category
        GROUP BY d.pk
     ) agg
WHERE b.pk = agg.pk;

此查询的结果是

 | id | pk |  b_total  |
 +----+----+-----------+
 |  1 | 14 |  273611   |
 |  2 | 15 |  273611   |
 |  3 | 16 |  273611   |
 |  4 | 17 |  273611   |

但如果我只运行SELECT,则每个 pk 的结果完全不同

 | pk |  agg.total  |
 +----+-------------+
 | 14 |    273611   |
 | 15 |    407802   |
 | 16 |    179996   |
 | 17 |    815580   |

问题

  • 为什么会这样?
  • 为什么WHERE子句不起作用?

在撰写此问题之前,我已将这些帖子用作参考:abc

2 个答案:

答案 0 :(得分:2)

执行以下操作(我总是建议不要更新更新中的联接)

UPDATE business_stats bs
SET b_total =
(  SELECT   count(c.id) total
        FROM business_details AS bd
        INNER JOIN datasets AS d
        ON bd.category = d.category
       where d.pk=bs.pk
 )
/*optional*/
where exists (SELECT  *
    FROM business_details AS bd
        INNER JOIN datasets AS d
        ON bd.category = d.category
   where d.pk=bs.pk)

答案 1 :(得分:1)

问题是你的FROM子句。重复引用business_stats意味着您不会像预期的那样限制联接。您正在加入agg以反对第二个不相关的business_stats提及,而不是您要更新的行。

这样的事情就是你所追求的(警告未经测试):

UPDATE business_stats AS b
SET b_total = agg.total
FROM
     (...) agg
WHERE b.pk = agg.pk;