Как вычислить среднее значение столбца, а затем включить его в запрос select в oracle?
мой стол--
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);
Я знаю, как рассчитать среднее значение по стоимости столбца, мой код-
select avg(cost) from mobile;
и в результате 123
но я хочу рассчитать среднее, а затем также показать разницу.Я смог это сделать, но я не могу добавить столбец avg в запрос select--
мой код ---
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
пожалуйста, помогите...
6 ответов
ваша группа-это то, что агрегирует ваше среднее значение, и оно группируется по всей таблице (я предполагаю, что вы сделали это, чтобы разрешить выбор для всего), просто переместите свой 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;
при запуске basic SELECT AVG(cost)
заявление это, естественно, группировка по указанному столбцу (стоимость в этом случае), поскольку это то, что вы запрашиваете. Я бы предложил прочитать больше на ГРУППЫ ПО и Сростки чтобы лучше понять концепцию. Это должно помочь вам более простое решение.
обновление:
ответ ниже на самом деле из ответа Дэвида. Он использует аналитические функции. В принципе, происходит то, что при каждом вызове AVG вы говорите движку, что использовать для функции (в этом случае ничего). Достойную запись по аналитическим функциям можно найти здесь и здесь и больше с google по этому вопросу.
SELECT id, m_name AS "Mobile Name" cost AS Price, AVG(cost) OVER( ) AS Average,
cost - AVG(cost) OVER ( ) AS Difference
FROM mobile
однако, если ваш SQL engine допускает переменные, вы можете так же легко сделать следующий ответ. Я действительно предпочитаю это для будущей ремонтопригодности / читаемости. Причина в том, что переменная с хорошим именем может быть очень описательной для будущих читателей кода по сравнению с аналитической функцией, которая требует немного больше работы для чтения (особенно если вы не понимаете функцию over).
кроме того, это решение дублирует один и тот же запрос дважды, поэтому, возможно, стоит сохранить среднее значение в переменной 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;
это решение будет читать намного чище для будущих читателей вашего SQL тоже
поскольку вы используете 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
Не нужны подзапросы или группы.
самое простое изменение-изменить avg(cost) as Average
to (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
;
попробовать
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;
если ваш запрос слишком дорог, таким образом, напишите мне рекомендацию, тогда я улучшу ее.
один из редких случаев 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
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