基本上,我开始的是TABLE_A
中的内容France - 100
France - 200
France - 300
Mexico - 50
Mexico - 50
Mexico - 56
Poland - 100
Poland - 150
最后我想要的是一个添加的列,其中包含按国家/地区划分的平均值。
France - 100 - 200
France - 200 - 200
France - 300 - 200
Mexico - 500 - 520
Mexico - 500 - 520
Mexico - 560 - 520
Poland - 100 - 125
Poland - 150 - 125
我想通过更新/更改TABLE_A而不是在可能的情况下创建新表来完成此操作。我在Oracle工作。谢谢你的任何想法!
答案 0 :(得分:2)
您可以使用avg() over()
。我没有看到存储这些计算列的原因。每次添加新行或表中的行更新时,都必须更新它们。
select t.*, avg(val) over(partition by country) average
from yourtable t
要将其添加为列,请执行以下操作:
alter yourtable add average number(10,2);
commit;
update yourtable t
set t.average = (select avg(val)
from yourtable
where country = t.country)
;
commit;
答案 1 :(得分:1)
简短的回答是:不要这样做。您可以通过功能完成某些操作,从而打破数据库规范化。正如您在Oracle中所做的那样,您可以使用RESULT CACHE子句编写一个函数,例如
FUNCTION average_by_country (country_id IN countries.id%TYPE)
RETURN countries.whatever%TYPE
RESULT_CACHE RELIES_ON (countries)
IS
等等,这将缓存每个国家的结果,使功能评估非常快。
然后,您可以使用
选择此平均值SELECT country_id, country_name, country_data, average_by_country(country_id)
FROM countries WHERE etc etc
答案 2 :(得分:0)
declare
cursor c_records is
select movie_id, count(*) cnt, avg(rating) avgr
from ratings
group by movie_id;
l_i number := 0;
begin
for l_rec in c_records loop
update movies
set avg_user_rating = l_rec.avgr,
rating_count = l_rec.cnt
where movie_id = l_rec.movie_id;
l_i := l_i + 1;
if mod(l_i, 1000) = 0 then
commit;
end if;
end loop;
end;
花了9秒,而
update movies m
set avg_user_rating =
(
select avg(r.rating)
from ratings r
where r.movie_id = m.movie_id
)
在9小时后被取消,因为它仍未完成。