我有几张表,想要更新另一张表:
create table first_table
(bookstore_id number not null,
event varchar2(10),
timestamp date);
create table second_table
(bookstore_id number,
numbooks number);
insert into second_table values (1,0);
insert into second_table values (2,0);
insert into second_table values (3,0);
insert into first_table values (1, 'ADD', sysdate);
insert into first_table values (1, 'ADD', sysdate);
insert into first_table values (1, 'ADD', sysdate);
insert into first_table values (1, 'REMOVE', sysdate);
insert into first_table values (1, 'ADD', sysdate);
insert into first_table values (1, 'REMOVE', sysdate);
insert into first_table values (2, 'ADD', sysdate);
insert into first_table values (2, 'ADD', sysdate);
insert into first_table values (2, 'REMOVE', sysdate);
insert into first_table values (2, 'ADD', sysdate);
insert into first_table values (2, 'ADD', sysdate);
insert into first_table values (2, 'ADD', sysdate);
insert into first_table values (3, 'ADD', sysdate);
insert into first_table values (3, 'ADD', sysdate);
insert into first_table values (3, 'REMOVE', sysdate);
insert into first_table values (3, 'ADD', sysdate);
insert into first_table values (3, 'REMOVE', sysdate);
insert into first_table values (3, 'ADD', sysdate);
insert into first_table values (3, 'REMOVE', sysdate);
以下逻辑可以满足我的需求:
begin
for storeid in (select bookstore_id from second_table)
loop
update second_table
set numbooks =
(select count(*) from first_table
where event = 'ADD'
and bookstore_id = storeid.bookstore_id)
- /* actual minus sign is needed here */
(select count(*) from first_table
where event = 'REMOVE'
and bookstore_id = storeid.bookstore_id)
where bookstore_id = storeid.bookstore_id;
end loop;
end;
/
我的问题是,这可以使用单个SQL语句来完成,避免循环吗?
答案 0 :(得分:2)
不需要CTE或其他任何东西,你可以这样做:
update second_table
set numbooks =
((select count(*) from first_table
where event = 'ADD'
and bookstore_id = second_table.bookstore_id)
- /* actual minus sign is needed here */
(select count(*) from first_table
where event = 'REMOVE'
and bookstore_id = second_table.bookstore_id))
实际上可以使用条件聚合来完成,并避免第一个表中的一个选择:
update second_table
set numbooks =
(select (count(CASE WHEN event = 'ADD' then 1 end)
-
count(CASE WHEN event = 'REMOVE' then 1 end))
from first_table
WHERE bookstore_id = second_table.bookstore_id)
WHERE EXISTS(select 1 from first_table s where second_table.bookstore_id = s.bookstore_id)
答案 1 :(得分:0)
您可以直接在SQL中执行此操作。以下是Oracle中的一种方法(其他数据库具有更简单的机制):
update second_table st
set numbooks = (select sum(case when event = 'ADD' then 1
when event = 'REMOVE' then -1
else 0
end)
from first_table ft
where st.bookstore_id = ft.bookstore_id
)
where exists (select 1 from first_table where st.bookstore_id = ft.bookstore_id);
请注意,where
子句仅更新第二个表中第一个表中的行。如果您知道所有行都在那里 - 或者您希望更新缺失的行(使用NULL
,可以轻松更改为0
) - 那么请不要包含它。
如果其他类型的事件有很多行,则子查询中的where event in ('ADD', 'REMOVE')
可能会使性能受益。