简体   繁体   English

如何计算列的平均值,然后将其包含在oracle的select查询中?

[英]How to calculate average of a column and then include it in a select query in oracle?

My table is-- 我的桌子是 -

create table mobile
(
  id integer,
  m_name  varchar(20),
  cost integer
)

and the values are -- 而价值观是 -

insert into mobile values(10,'NOkia',100);
insert into mobile values(11,'Samsung',150);
insert into mobile values(12,'Sony',120);

I know how to calculate average on column cost, my code is-- 我知道如何计算柱成本的平均值,我的代码是 -

 select avg(cost) from mobile;

and the result is 123 结果是123

But i want to calculate average and then also show the difference.I was able to this but, I am not able to add avg column in the select query-- 但我想计算平均值,然后也显示差异。我能够这样但但是,我无法在选择查询中添加avg列 -

My code is --- 我的代码是---

SELECT id, m_name as "Mobile Name", cost as Price,avg(cost) as Average,
cost-(select avg(cost) from mobile) as Difference FROM mobile
group by id,m_name,cost;

and the output is -- 输出是 -

id      Mobile Name   Price  Average  Difference 
10      Nokia         100    100      -23
11      Samsung       150    150       27
12      Sony          120    120      -3

what I wants is to correct this average column.. I wants this--- 我想要的是纠正这个平均列..我想要这个---

id      Mobile Name  Price  Average  Difference 
10      Nokia       100     123     -23
11      Samsung     150     123      27
12      Sony        120     123      -3

please help... 请帮忙...

Since you're using Oracle, you should be able to use AVG() as an analytic (window) function: 由于您使用的是Oracle,因此您应该能够使用AVG()作为分析(窗口)函数:

SELECT id, m_name AS "Mobile Name" cost AS Price, AVG(cost) OVER( ) AS Average
     , cost - AVG(cost) OVER ( ) AS Difference
  FROM mobile

No need for subqueries or GROUP BY. 不需要子查询或GROUP BY。

Your group by is what aggregates your average, and it is grouping by the whole table (I am assuming you did this to allow the select for everything) Just move your avg into another subquery, remove the overarching group by and that should solve it. 你的分组是汇总你的平均值,它是整个表的分组(我假设你这样做是为了允许选择所有的东西)只需将你的avg移动到另一个子查询中,删除总体分组,然后解决它。

SELECT id, m_name AS "Mobile Name", cost AS Price,
    (SELECT AVG(cost) FROM mobile) AS Average,
    cost-(SELECT AVG(cost) FROM mobile) AS Difference 
FROM mobile;

When you run the basic SELECT AVG(cost) statement it is naturally grouping by the column specified (cost in this case) as that is what you are requesting. 当您运行基本的SELECT AVG(cost)语句时,它自然按指定的列(在这种情况下为SELECT AVG(cost)分组,因为这是您请求的内容。 I would suggest reading up more on GROUP BY and aggregates to get a better grasp on the concept. 我建议阅读更多关于GROUP BY聚合的内容 ,以便更好地掌握这个概念。 That should help you more than just a simple solution. 这应该不仅仅是一个简单的解决方案。

UPDATE: 更新:

The answer below is actually from David's answer. 下面的答案实际上来自大卫的回答。 It makes use the analytical functions. 它利用了分析功能。 Basically, what is happening is that on each AVG call, you are telling the engine what to use for the function (in this case, nothing). 基本上,正在发生的事情是,在每个AVG调用中,您告诉引擎该功能使用什么(在这种情况下,什么都没有)。 A decent writeup on analytical functions can be found here and here and more with a google on the matter. 关于分析函数的一个体面的文章可以在这里这里找到,还有更多关于这个问题的谷歌。

SELECT id, m_name AS "Mobile Name" cost AS Price, AVG(cost) OVER( ) AS Average, 
    cost - AVG(cost) OVER ( ) AS Difference
    FROM mobile

However, if your SQL engine allows for variables, you could just as easily do the below answer. 但是,如果您的SQL引擎允许变量,您可以轻松地执行以下答案。 I actually prefer this for future maintainability/readability. 我实际上更喜欢这个用于将来的可维护性/可读性。 The reason is that a variable with a good name can be very descriptive to future readers of the code, versus an analytical function that does require a little bit more work to read (especially if you do not understand the over function). 原因是具有良好名称的变量可以非常描述代码的未来读者,而不是需要更多工作来阅读的分析函数(特别是如果您不理解过度函数)。

Also, this solution duplicates the same query twice, so it might be worth storing your average in a SQL variable. 此外,此解决方案复制相同的查询两次,因此可能值得将您的平均值存储在SQL变量中。 Then you ca change your statement to simply use that global average 然后你可以改变你的陈述,只需使用那个全局平均值

This is variables in SQL-Server (you will have to adapt it for your own instance of SQL) 这是SQL-Server中的变量(您必须根据自己的SQL实例调整它)

DECLARE @my_avg INT;
SELECT @my_avg = AVG(cost) FROM Mobile;

    SELECT id, m_name AS "Mobile Name", cost AS Price,
        @my_avg AS Average, cost-@my_avg AS Difference 
    FROM mobile;

This solution will read a lot cleaner to future readers of your SQL, too 此解决方案也将为您的SQL的未来读者提供更多清洁

The simplest change is to change avg(cost) as Average to (select avg(cost) from mobile) as Average . 最简单的变化是将avg(cost) as Average改为(select avg(cost) from mobile) as Average This also means that you won't need the GROUP BY clause anymore (since it doesn't do what you actually wanted): 这也意味着您将不再需要GROUP BY子句(因为它不会执行您真正想要的操作):

SELECT id,
       m_name AS "Mobile Name",
       cost AS "Price",
       (SELECT AVG(cost) FROM mobile) AS "Average",
       cost - (SELECT AVG(cost) FROM mobile) AS "Difference"
  FROM mobile
;
select pid, name, price as actualcost, 
       AVERAGE = (select AVG(price) from Part_Master), 
       price - (select AVG(price) as diff from Part_Master) AS COST_DIFF 
from   Part_Master

try 尝试

SELECT id, m_name as "Mobile Name", cost as Price,(select avg(cost) from mobile) as Average),
cost-(select avg(cost) from mobile) as Difference FROM mobile
group by id,m_name,cost;

if your query is too expensive that way drop me a commend then I'll improve it. 如果您的查询太昂贵,那么请给我一个推荐,然后我会改进它。

One of the rare times a CROSS JOIN is applicable: CROSS JOIN很少见的适用时间之一:

WITH avgcost as (select round(avg(cost)) as Average from mobile)
SELECT id, m_name as "Mobile Name", cost as Price, Average,
cost-Average as Difference
FROM mobile cross join avgcost

Which will result in: 这将导致:

ID  Mobile Name PRICE   AVERAGE DIFFERENCE
10  NOkia       100     123     -23
11  Samsung     150     123     27
12  Sony        120     123     -3

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

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