2016-06-12 1 views
1

Je dois compter le nombre d'employés par département avec un salaire supérieur à la moyenne.MySQL - ERREUR 1054 (42S22): Colonne inconnue 'sal' dans 'having clause'

Mes table employees:

+------+--------+-----------+------+------------+------+------+--------+ 
| eno | ename | job  | mgr | hiredate | sal | comm | deptno | 
+------+--------+-----------+------+------------+------+------+--------+ 
| 7369 | smith | clerk  | 7902 | 1980-12-17 | 800 | NULL |  20 | 
| 7499 | allen | salesman | 7698 | 1981-02-20 | 1600 | 300 |  30 | 
| 7521 | ward | salesman | 7698 | 1981-02-22 | 1250 | 500 |  30 | 
| 7566 | jones | manager | 7839 | 1981-04-02 | 2975 | NULL |  20 | 
| 7654 | martin | salesman | 7698 | 1981-10-28 | 1250 | 1400 |  30 | 
| 7698 | blake | manager | 7839 | 1981-05-01 | 2850 | NULL |  30 | 
| 7782 | clark | manager | 7839 | 1981-06-09 | 2450 | NULL |  10 | 
| 7788 | scott | analyst | 7566 | 1982-12-09 | 3000 | NULL |  20 | 
| 7839 | king | president | NULL | 1981-11-17 | 5000 | NULL |  10 | 
| 7844 | turner | salesman | 7698 | 1981-10-08 | 1500 | NULL |  30 | 
| 7876 | adams | clerk  | 7788 | 1983-01-12 | 1100 | NULL |  20 | 
| 7900 | james | clerk  | 7698 | 1981-12-03 | 950 | NULL |  30 | 
| 7902 | ford | analyst | 7566 | 1981-12-03 | 3000 | NULL |  20 | 
| 7934 | miller | clerk  | 7782 | 1982-01-23 | 1300 | NULL |  10 | 
+------+--------+-----------+------+------------+------+------+--------+ 

La requête que je suis en train de faire est

select deptno, count(*) from emp group by deptno having sal > avg(sal) 

Et c'est quand je reçois l'erreur.

J'ai essayé cette requête aussi:

select deptno, count(*), avg(sal) from emp group by deptno 

Ce qui est fondamentalement le même sauf qu'il n'y a pas de clause ayant, et cela fonctionne comme prévu.

-

select deptno, count(*) from emp where sal > avg(sal) group by deptno

Cette requête jette l'erreur suivante:

ERROR 1111 (HY000): Invalid use of group function

-

select deptno, count(*) from emp group by deptno where sal > avg(sal)

Et cette o n'utilise une syntaxe incorrecte:

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'where sal > avg(sal)' at line 1

-

Pourquoi ai-je cette erreur? Quelle serait la bonne façon d'exécuter cette requête? Merci d'avance.

Insertion de script:

SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO"; 
SET time_zone = "+00:00"; 

/*!40101 SET @[email protected]@CHARACTER_SET_CLIENT */; 
/*!40101 SET @[email protected]@CHARACTER_SET_RESULTS */; 
/*!40101 SET @[email protected]@COLLATION_CONNECTION */; 
/*!40101 SET NAMES utf8 */; 

CREATE TABLE IF NOT EXISTS `emp` (
    `eno` int(11) NOT NULL AUTO_INCREMENT, 
    `ename` varchar(30) DEFAULT NULL, 
    `job` varchar(30) DEFAULT NULL, 
    `mgr` int(11) DEFAULT NULL, 
    `hiredate` date DEFAULT NULL, 
    `sal` int(11) DEFAULT NULL, 
    `comm` int(11) DEFAULT NULL, 
    `deptno` int(11) DEFAULT NULL, 
    PRIMARY KEY (`eno`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=10000 ; 

INSERT INTO `emp` (`eno`, `ename`, `job`, `mgr`, `hiredate`, `sal`, `comm`, `deptno`) VALUES 
(7369, 'smith', 'clerk', 7902, '1980-12-17', 800, NULL, 20), 
(7499, 'allen', 'salesman', 7698, '1981-02-20', 1600, 300, 30), 
(7521, 'ward', 'salesman', 7698, '1981-02-22', 1250, 500, 30), 
(7566, 'jones', 'manager', 7839, '1981-04-02', 2975, NULL, 20), 
(7654, 'martin', 'salesman', 7698, '1981-10-28', 1250, 1400, 30), 
(7698, 'blake', 'manager', 7839, '1981-05-01', 2850, NULL, 30), 
(7782, 'clark', 'manager', 7839, '1981-06-09', 2450, NULL, 10), 
(7788, 'scott', 'analyst', 7566, '1982-12-09', 3000, NULL, 20), 
(7839, 'king', 'president', NULL, '1981-11-17', 5000, NULL, 10), 
(7844, 'turner', 'salesman', 7698, '1981-10-08', 1500, NULL, 30), 
(7876, 'adams', 'clerk', 7788, '1983-01-12', 1100, NULL, 20), 
(7900, 'james', 'clerk', 7698, '1981-12-03', 950, NULL, 30), 
(7902, 'ford', 'analyst', 7566, '1981-12-03', 3000, NULL, 20), 
(7934, 'miller', 'clerk', 7782, '1982-01-23', 1300, NULL, 10); 

/*!40101 SET [email protected]_CHARACTER_SET_CLIENT */; 
/*!40101 SET [email protected]_CHARACTER_SET_RESULTS */; 
/*!40101 SET [email protected]_COLLATION_CONNECTION */; 
+0

Quelle est votre version de MySQL? – Jocelyn

+0

https://dev.mysql.com/doc/refman/5.7/fr/group-by-handling.html Jetez un oeil – Naruto

+0

@Jocelyn J'utilise MySQL 5.5.24. – SoKeT

Répondre

1

Essayez de rejoindre l'ensemble avec la table

select emp.depnto, count(*) from 
(select deptno, avg(sal) avgsal from employees group by deptno) avg 
INNER JOIN employees emp on avg.deptno = avg.depnto 
WHERE emp.sal > avg.avgsal 

EDIT

Peut-être que je thoght à compliqué. Lorsque la moyenne globale est signifiée, il est simplement

select depnto, count(*) from employees 
where sal > (select avg(sal) from employees) 
group by deptno 
+0

Votre deuxième solution est celle Je cherchais, mais je ne sais toujours pas pourquoi cela ne fonctionne pas en utilisant "where sal> avg (sal)" et il utilise une autre requête à l'intérieur. J'apprécierais que vous puissiez éclaircir cela. Merci pour la solution cependant. – SoKeT

+0

dans le cas où vous ne pouvez pas utiliser avg car il y a la portée sur la seule ligne, sur laquelle plus tard l'agrégation fonctionnera. Dans la clause Having, la portée est le groupe, vous n'avez donc accès qu'aux fonctions d'agrégat sur les colonnes de la table et les colonnes de regroupement. Pour cela vous devez utiliser des sous-sélections si vous voulez des valeurs qui ne sont pas dans la portée de la ligne (groupe dans la clause having): le vlaue de l'agrégation détermine les lignes à agréger, comment cela pourrait-il fonctionner? – Turo

+0

Vous avez raison, je n'y ai jamais pensé de cette façon. Merci beaucoup pour la perspicacité, c'est vraiment utile. Merci encore pour la solution aussi. – SoKeT

0

Vous avez la virgule avant de

select deptno, count(*) 
from emp 
group by deptno having sal > (select avg(sal)from emp); 
+0

C'est une erreur de frappe ici sur Stack Overflow, mon mauvais; la requête ne fonctionne toujours pas. Merci d'avoir remarqué. – SoKeT

+0

J'ai mis à jour la réponse -.- avec une suggestion .. et pourquoi downvote ..le ansewer était correct – scaisEdge

+0

Je n'ai pas downvote et je ne sais pas pourquoi quelqu'un le ferait. Désolé pour ça. – SoKeT

1

Il n'y a pas besoin d'utiliser HAVING. Essayez OÙ à la place:

select deptno, count(*) from emp WHERE sal > avg(sal) group by deptno 
+0

Ne fonctionne pas, je pense que la clause where doit être avant le groupe. Votre requête renvoie cette erreur: 'Vous avez une erreur dans votre syntaxe SQL; consultez le manuel qui correspond à votre version du serveur MySQL pour la bonne syntaxe à utiliser près de 'where sal> avg (sal)' à la ligne 1'. – SoKeT

+0

Je pense que cela améliorerait votre réponse si vous pouviez expliquer un peu quand utiliser 'Avoir' contre 'Où'? – Martin

+0

OH désolé sélectionnez deptno, compte (*) à partir de emp WHERE sal> avg (sal) groupe par deptno –

0

Essayez cette

SELECT deptno as Department , count(eno) as employeeCount from emp 
where sal > (select avg(sal) from emp) group by deptno 
+0

'erreur 1242 (21000): sous-requête renvoie plus de 1 row' – SoKeT