Ma table est--
create table mobile
(
id integer,
m_name varchar(20),
cost integer
)
et les valeurs sont -
insert into mobile values(10,'NOkia',100);
insert into mobile values(11,'Samsung',150);
insert into mobile values(12,'Sony',120);
Je sais comment calculer le coût moyen d'une colonne, mon code est--
select avg(cost) from mobile;
et le résultat est 123
Mais je veux calculer la moyenne et montrer aussi la différence.J'ai pu le faire, mais je ne peux pas ajouter de colonne avg dans la requête select--
Mon code est ---
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;
et la sortie est -
id Mobile Name Price Average Difference
10 Nokia 100 100 -23
11 Samsung 150 150 27
12 Sony 120 120 -3
ce que je veux, c'est corriger cette colonne moyenne. Je veux ceci ---
id Mobile Name Price Average Difference
10 Nokia 100 123 -23
11 Samsung 150 123 27
12 Sony 120 123 -3
aidez s'il vous plaît ...
Votre groupe par est ce qui agrège votre moyenne, et il regroupe par la table entière (je suppose que vous avez fait cela pour permettre la sélection pour tout). Il vous suffit de déplacer votre avg dans une autre sous-requête, de supprimer le groupe global par et cela devrait le résoudre.
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;
Lorsque vous exécutez l'instruction SELECT AVG(cost)
de base, elle est naturellement groupée par la colonne spécifiée (coût dans ce cas) car c'est ce que vous demandez. Je suggérerais de lire davantage sur GROUP BY et agrégats pour mieux comprendre le concept. Cela devrait vous aider plus qu'une simple solution.
UPDATE:
La réponse ci-dessous provient de la réponse de David. Il utilise les fonctions analytiques. En gros, à chaque appel AVG, vous indiquez au moteur ce qu'il doit utiliser pour la fonction (dans ce cas, rien). Vous pouvez trouver une description décente des fonctions d’analyse ici et ici et plus encore avec un google sur le sujet.
SELECT id, m_name AS "Mobile Name" cost AS Price, AVG(cost) OVER( ) AS Average,
cost - AVG(cost) OVER ( ) AS Difference
FROM mobile
Toutefois, si votre moteur SQL autorise les variables, vous pouvez tout aussi bien répondre à la question ci-dessous. Je préfère en fait cela pour la maintenabilité/lisibilité future. La raison en est qu’une variable avec un bon nom peut être très descriptive pour les futurs lecteurs du code, par opposition à une fonction analytique qui nécessite un peu plus de travail à lire (surtout si vous ne comprenez pas la fonction over).
De plus, cette solution duplique deux fois la même requête. Il peut donc être intéressant de stocker votre moyenne dans une variable SQL. Ensuite, vous pouvez changer votre déclaration pour utiliser simplement cette moyenne globale
Il s'agit de variables dans SQL-Server (vous devrez l'adapter à votre propre instance de 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;
Cette solution lira aussi beaucoup plus propre pour les futurs lecteurs de votre code SQL
Puisque vous utilisez Oracle, vous devriez pouvoir utiliser AVG () en tant que fonction analytique (fenêtre):
SELECT id, m_name AS "Mobile Name" cost AS Price, AVG(cost) OVER( ) AS Average
, cost - AVG(cost) OVER ( ) AS Difference
FROM mobile
Pas besoin de sous-requêtes ou de GROUP BY.
Le changement le plus simple consiste à remplacer avg(cost) as Average
par (select avg(cost) from mobile) as Average
. Cela signifie également que vous n’avez plus besoin de la clause GROUP BY
(car elle ne fait pas ce que vous vouliez réellement):
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
essayer
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;
si votre requête est trop chère, envoyez-moi une recommandation, je l'améliorerai.
Un des rares cas où un CROSS JOIN
est applicable:
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
Ce qui entraînera:
ID Mobile Name PRICE AVERAGE DIFFERENCE
10 NOkia 100 123 -23
11 Samsung 150 123 27
12 Sony 120 123 -3