繁体   English   中英

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

[英]SQL - how to add column with average value, grouped

本质上,我从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并在可能的情况下不创建新表来做到这一点。 我在甲骨文工作。 感谢您的任何想法!

您可以使用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;

简短的答案是:不要那样做。 您正在破坏数据库的规范化,而这可以通过函数来​​完成。 在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
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小时后被取消,因为它仍未完成。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM