SQL - 如何添加具有平均值的列,已分组

时间:2016-03-31 18:00:43

标签: sql oracle group-by average

基本上,我开始的是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工作。谢谢你的任何想法!

3 个答案:

答案 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小时后被取消,因为它仍未完成。