使用子查询的WHERE中的相同表更新子查询

时间:2012-03-03 10:20:18

标签: sql count aggregate-functions sql-update

我在表“user”中有2个整数字段:leg_count和leg_length。第一个存储用户的腿数,第二个存储它们的总长度。

属于用户的每条腿都存储在单独的表中,只要典型的互联网用户可以有零到无限的腿:

CREATE TABLE legs (
    user_id int not null,
    length  int not null
);

我想在一个查询中重新计算所有用户的统计信息,因此我尝试:

UPDATE users SET
    leg_count = subquery.count, leg_length = subquery.length
FROM (
    SELECT COUNT(*) as count, SUM(length) as length FROM legs WHERE legs.user_id = users.id
) AS subquery;

并获取“FROM中的子查询不能引用相同查询级别的其他关系”错误。

所以我必须这样做

UPDATE users SET
    leg_count =  (SELECT COUNT(*)    FROM legs WHERE legs.user_id = users.id),
    leg_length = (SELECT SUM(length) FROM legs WHERE legs.user_id = users.id)

是什么让数据库为每一行执行2个SELECT,但是,所需数据可以在一个SELECT中计算:

SELECT COUNT(*), SUM(length) FROM legs;

是否可以优化我的UPDATE查询以仅使用一个SELECT子查询?

我使用PostgreSQL,但我相信,任何SQL方言都存在解决方案。

TIA。

2 个答案:

答案 0 :(得分:7)

我愿意:

WITH stats AS
   ( SELECT COUNT(*)    AS cnt
          , SUM(length) AS totlength
          , user_id
       FROM legs
      GROUP BY user_id
   )
UPDATE users
   SET leg_count = cnt, leg_length = totlength
  FROM stats
 WHERE stats.user_id = users.id

答案 1 :(得分:3)

您可以使用PostgreSQL的extended update syntax

update  users as u
set     leg_count = aggr.cnt
,       leg_length = aggr.length
from    (
        select  legs.user_id
        ,       count(*) as cnt
        ,       sum(length) as length 
        from    legs 
        group by
                legs.user_id
        ) as aggr
where   u.user_id = aggr.user_id