2016-01-23 123 views
0

我有一個經典的父母 - 子女關係的sqlite:更新多個列一個子查詢

create table tq84_parent (
    id    int primary key, 
    avg_val   float, 
    min_val   float, 
    max_val   float 
); 

create table tq84_child (
    id_parent   int references tq84_parent, 
    val    int 
); 

這是充滿如下

insert into tq84_parent (id) values(1); 
insert into tq84_parent (id) values(2); 

insert into tq84_child values (1, 1); 
insert into tq84_child values (1, 2); 
insert into tq84_child values (1, 3); 

insert into tq84_child values (2, 6); 
insert into tq84_child values (2, 7); 
insert into tq84_child values (2, 8); 
insert into tq84_child values (2, 9); 
insert into tq84_child values (2, 10); 

現在,我想更新tq84_parent其列avg_valmin_valmax_val反映其子表的相應聚合值。

我可以用這個語句實現這一目標:

update 
    tq84_parent 
set 
    avg_val = (select avg(val) from tq84_child where id_parent = id), 
    min_val = (select min(val) from tq84_child where id_parent = id), 
    max_val = (select max(val) from tq84_child where id_parent = id); 

的結果,期望是:

.mode columns 

select * from tq84_parent; 

1   2.0   1.0   3.0 
2   8.0   6.0   10.0 

我擔心,但是,這樣的語句的性能不是最優的,因爲記錄數在tq84_parenttq84_child中都增長,因爲幾乎相同的查詢是三次而不是一次。

所以,我想一起去像

update 
    tq84_parent 
set 
(
    avg_val, 
    min_val, 
    max_val 
) 
= (select 
    avg(val), 
    min(val), 
    max(val) 
    from 
    tq84_child 
    where 
    id_parent = id 
); 

不工作。

那麼,有沒有辦法重寫我的查詢?

+0

這是您的實際'tq84_parent'表,還是有更多的列? –

+0

'tq84_parent'中有更多列。如果它有所作爲,我仍然對它的實際'tq84_parent'表有興趣。 –

回答

1

由於idid_parent是主鍵和外鍵,這意味着id是唯一的,而id_parent總是引用現有的ID。

這意味着你可以使用REPLACE更改表,因爲唯一密鑰總是違反(又名沒有插入會做),並REPLACE可以採取一個子查詢,並立即設置多個欄目;

REPLACE INTO tq84_parent (id, avg_val, min_val, max_val) 
    SELECT id_parent, AVG(val), MIN(val), MAX(val) 
    FROM tq84_child 
    GROUP BY id_parent; 

An SQLfiddle to test with

注:由於CL指出,由於行是更換,不更新未在查詢中設置字段將有自己的缺省值。這意味着如果表格中的其他字段需要保持不變,那麼舊方法仍然是實現它的方法。

+1

REPLACE從不更新表格,它只是刪除舊的行。 –

+0

@CL。你當然是對的,這就是我在第一杯咖啡前回答數據庫問題所得到的結果。謝謝。 –

0

查詢執行的實際速度主要取決於需要完成的磁盤I/O數量。

通過上面顯示的數據庫模式,每個子查詢都需要掃描整個表。 如果您在計算聚合值所需的所有列上都有覆蓋索引,則每個子查詢只需掃描索引的一小部分,因此實際上,在執行多個子查詢時,確保數據已存在於緩存中相同的ID:

CREATE INDEX xxx ON tq84_child(id_parent, val);