2012-03-03 95 views
1

我有一個表「user」中的2個整數字段:leg_count和leg_length。第一個存儲用戶的腿部數量和第二個 - 他們的總長度。UPDATE FROM子查詢在子查詢的WHERE中使用相同的表

每一個屬於用戶的腿被保存在單獨的表,就典型的互聯網用戶可以零到無窮大的腿:

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。

回答

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 
+0

'users.id',你所有。 – Tobu 2012-03-03 10:41:27

+1

你應該提到這需要PostgreSQL 9.1 – 2012-03-03 11:33:50

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