Как вычислить среднее значение столбца и затем включить его в запрос 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 ответов:
Ваша группа by-это то, что агрегирует ваше среднее значение, и это группировка по всей таблице (я предполагаю, что вы сделали это, чтобы разрешить выбор для всего) просто переместите ваш avg в другой подзапрос, удалите всеобъемлющую группу 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 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-движок допускает переменные, вы можете так же легко сделать следующий ответ. Я на самом деле предпочитаю это для будущей ремонтопригодности/читаемости. Причина в том, что переменная с хорошим именем может быть очень описательной для будущих читателей кода, в отличие от аналитической функции, которая требует немного больше работы для чтения (особенно если вы не понимаете функцию over).
Кроме того, это решение дублирует один и тот же запрос дважды, поэтому оно возможно, стоит сохранить ваше среднее значение в переменной SQL. Затем вы можете изменить свое утверждение, чтобы просто использовать это глобальное среднее значение
Это переменные в 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, 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на(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;Если ваш запрос слишком дорог таким образом, напишите Мне похвалу, тогда я улучшу его.
Один из редких случаев a
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
Comments