2012-03-10 82 views
6

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

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

和值是 -

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

我知道如何在列成本计算平均,我的代码is--

select avg(cost) from mobile; 

和结果是

但是iw蚂蚁计算平均值,然后还显示difference.I能够这样,但是,我不能够在选择query--

我的代码添加平均列---

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; 

和输出 -

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

什么,我想要的是纠正这个平均列。我想这---

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

请帮助...

+3

用于提供'create table'和样本数据为'insert',但这不是有效的Oracle语法(Oracle没有'bigint'或'int)。数字不应该放在单引号中! – 2012-03-10 15:55:52

+1

@JustinPihony,你可以使用'[faq]',[faq],'[ask]',[ask]等来代替,请参阅http://stackoverflow.com/editing-help#comment-formatting – Ben 2012-03-10 16:31:45

+0

@Ben谢谢,我一直在寻找评论格式。非常感激。 – 2012-03-10 16:45:40

回答

9

你按什么聚合你的平均,它是由整个表分组(我假设你这样做是为了允许选择所有东西)只要将你的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; 

当您运行的基本SELECT AVG(cost)声明它,自然是指定(在这种情况下成本)为列分组是您要求什么。我建议您阅读GROUP BYaggregates以更好地理解这个概念。这应该不仅仅是一个简单的解决方案。

UPDATE:

答案下面实际上是从大卫的回答。它使用分析功能。基本上,发生的情况是,在每个AVG调用中,您都在告诉引擎该函数使用什么(在这种情况下,什么都没有)。关于分析功能的一个体面的写法可以找到herehere和更多与谷歌有关的问题。

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

但是,如果你的SQL引擎允许变量,你可以轻松地做下面的答案。我其实更喜欢这种方式以保证未来的可维护性/可读性原因是具有良好名称的变量对于未来的代码读者可能是非常具有描述性的,而对于需要更多工作来阅读的分析函数(尤其是如果您不了解over函数的话)。

此外,此解决方案重复两次相同的查询,因此可能值得将平均值存储在SQL变量中。然后,你CA改变你的语句简单地使用全球平均

这是SQL-服务器(你将不得不去适应它自己的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, [email protected]_avg AS Difference 
    FROM mobile; 

该解决方案将读了很多变数清洁您的SQL未来的读者,也

+0

我很确定David的查询至少是有效的,并且不需要使用PL/SQL块,它需要您将SELECT的结果放入变量中 - 它不会以您编写它的方式显示(实际上我认为它甚至不会运行)。此外,重复查询只能由Oracle运行一次。我很确定优化器足够聪明,可以检测到这一点。 – 2012-03-10 16:21:57

+0

我很感谢你的解释,但PL/SQL块是完全错误的。这种方法在Oracle中将无法使用。如果您不想重复avg()查询,请使用分析函数或交叉连接解决方​​案。 – 2012-03-10 16:29:57

+0

这不会使PL/SQL正确。它仍然*错误*和**不会运行** – 2012-03-10 16:44:22

0

尝试

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; 

如果您的查询是太昂贵了这种方式给我发一个表彰然后我会改进。

2

最简单的变化是将avg(cost) as Average更改为(select avg(cost) from mobile) as Average。这也意味着你将不再需要在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 
; 
0

一个罕见时代的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 

这将导致:

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

由于您使用的是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 

无需子查询或GROUP BY。

+1

+ 1善用分析功能:) – 2012-03-10 16:52:26

0
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