Oracle SQL sample database - sql

I'm trying to learn Oracle SQL by database Supplied by it.
I found somewhere tasks to be done.
Database structure is supplied by Oracle:
CREATE TABLE EMP
(EMPNO NUMERIC(4) NOT NULL,
ENAME VARCHAR(10),
JOB VARCHAR(9),
MGR NUMERIC(4),
HIREDATE DATETIME,
SAL NUMERIC(7, 2),
COMM NUMERIC(7, 2),
DEPTNO NUMERIC(2))
INSERT INTO EMP VALUES
(7369, 'SMITH', 'CLERK', 7902, '17-DEC-1980', 800, NULL, 20)
INSERT INTO EMP VALUES
(7499, 'ALLEN', 'SALESMAN', 7698, '20-FEB-1981', 1600, 300, 30)
INSERT INTO EMP VALUES
(7521, 'WARD', 'SALESMAN', 7698, '22-FEB-1981', 1250, 500, 30)
INSERT INTO EMP VALUES
(7566, 'JONES', 'MANAGER', 7839, '2-APR-1981', 2975, NULL, 20)
INSERT INTO EMP VALUES
(7654, 'MARTIN', 'SALESMAN', 7698, '28-SEP-1981', 1250, 1400, 30)
INSERT INTO EMP VALUES
(7698, 'BLAKE', 'MANAGER', 7839, '1-MAY-1981', 2850, NULL, 30)
INSERT INTO EMP VALUES
(7782, 'CLARK', 'MANAGER', 7839, '9-JUN-1981', 2450, NULL, 10)
INSERT INTO EMP VALUES
(7788, 'SCOTT', 'ANALYST', 7566, '09-DEC-1982', 3000, NULL, 20)
INSERT INTO EMP VALUES
(7839, 'KING', 'PRESIDENT', NULL, '17-NOV-1981', 5000, NULL, 10)
INSERT INTO EMP VALUES
(7844, 'TURNER', 'SALESMAN', 7698, '8-SEP-1981', 1500, 0, 30)
INSERT INTO EMP VALUES
(7876, 'ADAMS', 'CLERK', 7788, '12-JAN-1983', 1100, NULL, 20)
INSERT INTO EMP VALUES
(7900, 'JAMES', 'CLERK', 7698, '3-DEC-1981', 950, NULL, 30)
INSERT INTO EMP VALUES
(7902, 'FORD', 'ANALYST', 7566, '3-DEC-1981', 3000, NULL, 20)
INSERT INTO EMP VALUES
(7934, 'MILLER', 'CLERK', 7782, '23-JAN-1982', 1300, NULL, 10)
CREATE TABLE DEPT
(DEPTNO NUMERIC(2),
DNAME VARCHAR(14),
LOC VARCHAR(13) )
INSERT INTO DEPT VALUES (10, 'ACCOUNTING', 'NEW YORK')
INSERT INTO DEPT VALUES (20, 'RESEARCH', 'DALLAS')
INSERT INTO DEPT VALUES (30, 'SALES', 'CHICAGO')
INSERT INTO DEPT VALUES (40, 'OPERATIONS', 'BOSTON')
CREATE TABLE BONUS
(ENAME VARCHAR(10),
JOB VARCHAR(9),
SAL NUMERIC,
COMM NUMERIC)
CREATE TABLE SALGRADE
(GRADE NUMERIC,
LOSAL NUMERIC,
HISAL NUMERIC)
INSERT INTO SALGRADE VALUES (1, 700, 1200)
INSERT INTO SALGRADE VALUES (2, 1201, 1400)
INSERT INTO SALGRADE VALUES (3, 1401, 2000)
INSERT INTO SALGRADE VALUES (4, 2001, 3000)
INSERT INTO SALGRADE VALUES (5, 3001, 9999)
Now I would like to Select employees that earn most in their department and salgrade.
I wrote something like this one:
select ename, salgrade.grade, dept.dname from emp, salgrade, dept
WHERE emp.sal BETWEEN salgrade.losal AND salgrade.hisal
AND emp.deptno = dept.deptno group by salgrade.grade, dept.dname, emp.ename
But it's not working properly.
The output is:
ENAME GRADE DNAME
SMITH 1 RESEARCH
BLAKE 4 SALES
FORD 4 RESEARCH
KING 5 ACCOUNTING
SCOTT 4 RESEARCH
MILLER 2 ACCOUNTING
TURNER 3 SALES
WARD 2 SALES
MARTIN 2 SALES
ADAMS 1 RESEARCH
JONES 4 RESEARCH
JAMES 1 SALES
CLARK 4 ACCOUNTING
ALLEN 3 SALES
Note rows:
WARD 2 SALES
MARTIN 2 SALES
2 people from same department and salgrade.
Could you point me my mistakes?

You are not filtering your query this is why you have all the employees displayed.
This would filter the employees that earn less than the max for their dept/grade:
SELECT ename, salgrade.grade, dept.dname
FROM emp, salgrade, dept
WHERE emp.sal BETWEEN salgrade.losal AND salgrade.hisal
AND emp.deptno = dept.deptno
AND emp.sal = (SELECT MAX(sal)
FROM emp emp_in, salgrade grade_in
WHERE emp_in.sal BETWEEN grade_in.losal AND grande_in.hisal
AND emp_in.deptno = emp.deptno
AND grade_in.losal = salgrade.losal)
You will still find duplicates because for instance, two people in sales earn the max salary for grade 2 (both Martin and Ward earn 1250). Either this is acceptable or you need some other criteria to only select one of them.
You can use the row_number analytic function to ensure that only one row is returned by grade/dept (note that Oracle will select arbitrarily one row when there are duplicates) :
SELECT * FROM (
SELECT ename, salgrade.grade, dept.dname,
row_number() OVER (PARTITION BY dept.deptno, salgrade.grade
ORDER BY emp.sal DESC) rnk
FROM emp, salgrade, dept
WHERE emp.sal BETWEEN salgrade.losal AND salgrade.hisal
AND emp.deptno = dept.deptno
) WHERE rnk = 1;
ENAME GRADE DNAME RNK
---------- ------ -------------- ---
MILLER 2 ACCOUNTING 1
CLARK 4 ACCOUNTING 1
KING 5 ACCOUNTING 1
ADAMS 1 RESEARCH 1
FORD 4 RESEARCH 1
JAMES 1 SALES 1
MARTIN 2 SALES 1
ALLEN 3 SALES 1
BLAKE 4 SALES 1

With your `select:
select ename, salgrade.grade, dept.dname from emp, salgrade, dept
WHERE emp.sal BETWEEN salgrade.losal AND salgrade.hisal
AND emp.deptno = dept.deptno group by salgrade.grade, dept.dname, emp.ename
when you group by salgrade.grade, dept.dname, emp.ename the results will be grouped into those three values. You also put the results BETWEEN salgrade.losal AND salgrade.hisal so it will give all employees that have the salary in that interval. It's not restricting anything to the greater one got it? And that's why you have WARD 2 SALES and MARTIN 2 SALES.

You are grouping by employee name, as well as department and salary grade. That means you will return a row for every combination of employee name, department and salary grade in your dataset.
To ensure that you only return one row per department and salary grade, you will need to remove the employee name from the group by clause. This will enable you to find the maximum salary per grade and department, but not which employees have that salary - to do that, you need to join the results back to the employee table again, like so:
select e.ename, s.grade, d.dname, e.salary
from (select max(emp.salary) max_salary,
salgrade.grade,
emp.deptno
from emp, salgrade
WHERE emp.sal BETWEEN salgrade.losal AND salgrade.hisal
group by salgrade.grade, dept.dname) s
join emp e on e.salary = s.max_salary
join dept d on e.deptno = d.deptno
Note that if multiple employees in the same department are earning the same maximum salary within their grade, then both employees will be returned - this should happen with FORD and SCOTT in RESEARCH.

SELECT SUB2.ENAME , SUB2.DNAME , S.GRADE ,SUB2.SAL
FROM SALGRADE S,
(SELECT E.ENAME,E.SAL,D.DNAME
FROM EMP E, DEPT D,
(SELECT DEPTNO, MAX(SAL) AS "MAX"
FROM EMP
GROUP BY DEPTNO) SUB1
WHERE E.SAL=SUB1.MAX
AND E.DEPTNO=D.DEPTNO) SUB2
WHERE SUB2.SAL BETWEEN S.LOSAL AND S.HISAL

Screen Shot ////// Try this out
SELECT E.EMPNO, E.ENAME, E.JOB, D.DNAME, E.SAL, E.DEPTNO, S.GRADE
FROM EMP E, SALGRADE S, DEPT D
WHERE E.SAL IN (SELECT MAX(SAL) FROM EMP GROUP BY DEPTNO)
AND E.SAL BETWEEN S.LOSAL AND S.HISAL
AND E.DEPTNO = D.DEPTNO
ORDER BY E.SAL DESC

When I created this I used this format to make it easier to read and modify it is for an Oracle format
CREATE TABLE EMP
(EMP_NO NUMBER(4) NOT NULL PRIMARY KEY,
E_NAME VARCHAR2(10),
JOB VARCHAR2(9),
MGR NUMBER(4),
HIRE_DATE DATE,
SAL DECIMAL(7, 2),
COMM DECIMAL(7, 2),
DEPT_NO NUMBER(2));
SELECT *
FROM EMP
INSERT INTO EMP
(EMP_NO, E_NAME, JOB, MGR, HIRE_DATE, SAL, COMM, DEPT_NO)
VALUES
(7369, 'SMITH', 'CLERK', 7902, '17-DEC-1980', 800, NULL, 20);
INSERT INTO EMP
(EMP_NO, E_NAME, JOB, MGR, HIRE_DATE, SAL, COMM, DEPT_NO)
VALUES
(7499, 'ALLEN', 'SALESMAN', 7698, '20-FEB-1981', 1600, 300, 30);
INSERT INTO EMP
(EMP_NO, E_NAME, JOB, MGR, HIRE_DATE, SAL, COMM, DEPT_NO)
VALUES
(7521, 'WARD', 'SALESMAN', 7698, '22-FEB-1981', 1250, 500, 30);
INSERT INTO EMP
(EMP_NO, E_NAME, JOB, MGR, HIRE_DATE, SAL, COMM, DEPT_NO)
VALUES
(7566, 'JONES', 'MANAGER', 7839, '02-APR-1981', 2975, NULL, 20);
INSERT INTO EMP
(EMP_NO, E_NAME, JOB, MGR, HIRE_DATE, SAL, COMM, DEPT_NO)
VALUES
(7654, 'MARTIN', 'SALESMAN', 7698, '28-SEP-1981', 1250, 1400, 30);
INSERT INTO EMP
(EMP_NO, E_NAME, JOB, MGR, HIRE_DATE, SAL, COMM, DEPT_NO)
VALUES
(7698, 'BLAKE', 'MANAGER', 7839, '01-MAY-1981', 2850, NULL, 30);
INSERT INTO EMP
(EMP_NO, E_NAME, JOB, MGR, HIRE_DATE, SAL, COMM, DEPT_NO)
VALUES
(7782, 'CLARK', 'MANAGER', 7839, '09-JUN-1981', 2450, NULL, 10);
INSERT INTO EMP
(EMP_NO, E_NAME, JOB, MGR, HIRE_DATE, SAL, COMM, DEPT_NO)
VALUES
(7788, 'SCOTT', 'ANALYST', 7566, '09-DEC-1982', 3000, NULL, 20);
INSERT INTO EMP
(EMP_NO, E_NAME, JOB, MGR, HIRE_DATE, SAL, COMM, DEPT_NO)
VALUES
(7839, 'KING', 'PRESIDENT', NULL, '17-NOV-1981', 5000, NULL, 10);
INSERT INTO EMP
(EMP_NO, E_NAME, JOB, MGR, HIRE_DATE, SAL, COMM, DEPT_NO)
VALUES
(7844, 'TURNER', 'SALESMAN', 7698, '08-SEP-1981', 1500, 0, 30);
INSERT INTO EMP
(EMP_NO, E_NAME, JOB, MGR, HIRE_DATE, SAL, COMM, DEPT_NO)
VALUES
(7876, 'ADAMS', 'CLERK', 7788, '12-JAN-1983', 1100, NULL, 20);
INSERT INTO EMP
(EMP_NO, E_NAME, JOB, MGR, HIRE_DATE, SAL, COMM, DEPT_NO)
VALUES
(7900, 'JAMES', 'CLERK', 7698, '03-DEC-1981', 950, NULL, 30);
INSERT INTO EMP
(EMP_NO, E_NAME, JOB, MGR, HIRE_DATE, SAL, COMM, DEPT_NO)
VALUES
(7902, 'FORD', 'ANALYST', 7566, '03-DEC-1981', 3000, NULL, 20);
INSERT INTO EMP
(EMP_NO, E_NAME, JOB, MGR, HIRE_DATE, SAL, COMM, DEPT_NO)
VALUES
(7934, 'MILLER', 'CLERK', 7782, '23-JAN-1982', 1300, NULL, 10);
CREATE TABLE DEPT
(DEPT_NO NUMERIC(2),
D_NAME VARCHAR(14),
LOC VARCHAR(13) );
INSERT INTO DEPT
(DEPT_NO, D_NAME, LOC)
VALUES
(10, 'ACCOUNTING', 'NEW YORK');
INSERT INTO DEPT
(DEPT_NO, D_NAME, LOC)
VALUES
(20, 'RESEARCH', 'DALLAS');
INSERT INTO DEPT
(DEPT_NO, D_NAME, LOC)
VALUES
(30, 'SALES', 'CHICAGO');
INSERT INTO DEPT
(DEPT_NO, D_NAME, LOC)
VALUES
(40, 'OPERATIONS', 'BOSTON');
CREATE TABLE BONUS
(E_NAME VARCHAR(10),
JOB VARCHAR(9),
SAL NUMERIC,
COMM NUMERIC);
CREATE TABLE SAL_GRADE
(GRADE NUMERIC,
LO_SAL NUMERIC,
HI_SAL NUMERIC);
INSERT INTO SAL_GRADE
(GRADE, LO_SAL, HI_SAL)
VALUES
(1, 700, 1200);
INSERT INTO SAL_GRADE
(GRADE, LO_SAL, HI_SAL)
VALUES
(2, 1201, 1400);
INSERT INTO SAL_GRADE
(GRADE, LO_SAL, HI_SAL)
VALUES
(3, 1401, 2000);
INSERT INTO SAL_GRADE
(GRADE, LO_SAL, HI_SAL)
VALUES
(4, 2001, 3000);
INSERT INTO SAL_GRADE
(GRADE, LO_SAL, HI_SAL)
VALUES
(5, 3001, 9999);

Related

How to know departments without male employes

We have two tables
Department
Emp
Department
CREATE TABLE department
(
deptno int NOT NULL,
dname varchar2(50) NOT NULL,
loc varchar2(13)
);
INSERT INTO DEPT (DEPTNO, DNAME, LOC)
VALUES (10, 'ACCOUNTING', 'NEW YORK');
INSERT INTO DEPT (DEPTNO, DNAME, LOC)
VALUES (20, 'RESEARCH', 'DALLAS');
INSERT INTO DEPT (DEPTNO, DNAME, LOC)
VALUES (30, 'SALES', 'CHICAGO');
INSERT INTO DEPT (DEPTNO, DNAME, LOC)
VALUES (40, 'OPERATIONS', 'BOSTON');
CREATE TABLE emp
(
empno number(4,0),
ename varchar2(10),
sex varchar2(10),
deptno number(2,0)
)
INSERT INTO emp
VALUES (7839, 'KING', 'PRESIDENT', Male, 10);
INSERT INTO emp
VALUES (7898, 'BLAKE', 'MANAGER', Male, 30);
INSERT INTO emp
VALUES (7782, 'CLARK', 'MANAGER', Female, 10);
INSERT INTO emp
VALUES (7566, 'JONES', 'ANALYST', Female, 20);
INSERT INTO emp
VALUES (7788, 'SCOTT', 'ANALYST', Male, 20);
INSERT INTO emp
VALUES (7902, 'FORD', 'ANALYST', Male, 20);
INSERT INTO emp
VALUES (7369, 'SMITH', 'CLERK', Female, 20);
INSERT INTO emp
VALUES (7369, 'Allen', 'Manager', Male, 40);
COMMIT;
Need a list of departments without a female employee....
Thanks
Raju
I got a list of departments with female employees and removed them from the entire list.
select deptno
from emp
where deptno not in (select deptno
from emp
where sex = 'Female');
I wanted to know if there is a better way to do it
You can use NOT EXISTS:
select *
from dept
where not exists (
select 1 from emp where emp.deptno = dept.deptno and emp.sex = 'Female'
)
Or the easier to read NOT IN, though probably less performant:
select *
from dept
where deptno not in (select deptno from emp where sex = 'Female')
Something like
SELECT
deptno,
sum(CASE sex WHEN 'Female' THEN 1 ELSE 0 END) AS number_female
FROM emp
GROUP BY deptno;
might work. You would need to select those department numbers with number_females = 0 But apart from that I can not come up with a solution that is shorter than yours. The table department seems to be irrelevant in this case, unless you need department names.

How to use listagg function in case statement?

select
case
when EMP.JOB in ('CLERK','SALESMAN')
then listagg (DISTINCT EMP.SAL, ';') within group (order by EMP.EMPNO)
end as sal
from
EMP
where
EMP.COMM is not null
group by
EMP.EMPNO
I am getting this error
ORA-00979: not a GROUP BY expression' when running this query.
This is the database to run this query:
CREATE TABLE EMP
(
EMPNO NUMBER(4) NOT NULL,
ENAME VARCHAR2(10),
JOB VARCHAR2(9),
MGR NUMBER(4),
HIREDATE DATE,
SAL NUMBER(7, 2),
COMM NUMBER(7, 2),
DEPTNO NUMBER(2)
);
INSERT INTO EMP
VALUES (7369, 'SMITH', 'CLERK', 7902, TO_DATE('17-DEC-1980', 'DD-MON-YYYY'), 800, NULL, 20);
INSERT INTO EMP
VALUES (7499, 'ALLEN', 'SALESMAN', 7698, TO_DATE('20-FEB-1981', 'DD-MON-YYYY'), 1600, 300, 30);
INSERT INTO EMP
VALUES (7521, 'WARD', 'SALESMAN', 7698, TO_DATE('22-FEB-1981', 'DD-MON-YYYY'), 1250, 500, 30);
INSERT INTO EMP
VALUES (7566, 'JONES', 'MANAGER', 7839, TO_DATE('2-APR-1981', 'DD-MON-YYYY'), 2975, NULL, 20);
INSERT INTO EMP
VALUES (7654, 'MARTIN', 'SALESMAN', 7698, TO_DATE('28-SEP-1981', 'DD-MON-YYYY'), 1250, 1400, 30);
INSERT INTO EMP
VALUES (7698, 'BLAKE', 'MANAGER', 7839, TO_DATE('1-MAY-1981', 'DD-MON-YYYY'), 2850, NULL, 30);
INSERT INTO EMP
VALUES (7782, 'CLARK', 'MANAGER', 7839, TO_DATE('9-JUN-1981', 'DD-MON-YYYY'), 2450, NULL, 10);
INSERT INTO EMP
VALUES (7788, 'SCOTT', 'ANALYST', 7566, TO_DATE('09-DEC-1982', 'DD-MON-YYYY'), 3000, NULL, 20);
INSERT INTO EMP
VALUES (7839, 'KING', 'PRESIDENT', NULL, TO_DATE('17-NOV-1981', 'DD-MON-YYYY'), 5000, NULL, 10);
INSERT INTO EMP
VALUES (7844, 'TURNER', 'SALESMAN', 7698, TO_DATE('8-SEP-1981', 'DD-MON-YYYY'), 1500, 0, 30);
INSERT INTO EMP
VALUES (7876, 'ADAMS', 'CLERK', 7788, TO_DATE('12-JAN-1983', 'DD-MON-YYYY'), 1100, NULL, 20);
INSERT INTO EMP
VALUES (7900, 'JAMES', 'CLERK', 7698, TO_DATE('3-DEC-1981', 'DD-MON-YYYY'), 950, NULL, 30);
INSERT INTO EMP
VALUES (7902, 'FORD', 'ANALYST', 7566, TO_DATE('3-DEC-1981', 'DD-MON-YYYY'), 3000, NULL, 20);
INSERT INTO EMP
VALUES (7934, 'MILLER', 'CLERK', 7782, TO_DATE('23-JAN-1982', 'DD-MON-YYYY'), 1300, NULL, 10);
The way you've written the code, you would need to group by EMP.JOB - that not being included is what the error is referring to:
select
case
when EMP.JOB in ('CLERK','SALESMAN')
then LISTAGG (DISTINCT EMP.SAL, ';') WITHIN GROUP ( ORDER BY EMP.EMPNO)
end as sal
from EMP
where EMP.COMM is not null
group by EMP.EMPNO, EMP.JOB
SAL
1600
1250
1250
1500
That doesn't seem to be what you want, though, since it doesn't actually aggregate - well, it does, but as each employee has a single salary and job, you get one row for each employee, with its single salary aggregated, which is the same as not aggregating.
You could put the case expression inside the listagg() instead:
select
LISTAGG (
DISTINCT case
when EMP.JOB in ('CLERK','SALESMAN')
then EMP.SAL
end,
';')
WITHIN GROUP (ORDER BY EMP.EMPNO) as sal
from EMP
where EMP.COMM is not null;
SAL
1600;1250;1500
which works but the order looks strange - it doesn't really make sense to order by the employee ID, particularly when you're eliminating duplicates. (I'm slightly surprised it doesn't complain - as you have a distinct salary, if that applies to more than one EMPNO, which one does it use in the ordering?)
Something like this is simpler, and I've switched the order to be in SAL order, which looks a bit more useful perhaps:
select
LISTAGG (DISTINCT EMP.SAL, ';') WITHIN GROUP (ORDER BY EMP.SAL) as sal
from EMP
where EMP.JOB in ('CLERK','SALESMAN')
and EMP.COMM is not null;
SAL
1250;1500;1600
fiddle
(Maybe still slightly surprising that it doesn't mind the DISTINCT and ORDER BY referring to the same column, but at least it's less ambiguous now...)

Find sum of salary from department where sum of salary is smaller than 20000

I'm trying to write a query that returns the total salary of every department.
So it needs to look who works in a department and count the salary up and do this for every department. Then it should only show me the departments that have a total salary lower than 20000.
My database looks like this
create table dept
(
deptno number(2,0),
dname varchar2(14),
loc varchar2(13),
constraint pk_dept primary key (deptno)
);
create table emp
(
empno number(4,0),
ename varchar2(10),
job varchar2(9),
mgr number(4,0),
hiredate date,
sal number(7,2),
comm number(7,2),
deptno number(2,0),
constraint pk_emp primary key (empno),
constraint fk_deptno foreign key (deptno) references dept (deptno)
);
insert into dept
values(10, 'ACCOUNTING', 'NEW YORK');
insert into dept
values(20, 'RESEARCH', 'DALLAS');
insert into dept
values(30, 'SALES', 'CHICAGO');
insert into dept
values(40, 'OPERATIONS', 'BOSTON');
insert into emp
values(7839, 'KING', 'PRESIDENT', null, to_date('17-11-1981','dd-mm-yyyy'), 5000, null, 10);
insert into emp
values(7698, 'BLAKE', 'MANAGER', 7839, to_date('1-5-1981','dd-mm-yyyy'), 2850, null, 30);
insert into emp
values(7782, 'CLARK', 'MANAGER', 7839, to_date('9-6-1981','dd-mm-yyyy'), 2450, null, 10);
insert into emp
values(7566, 'JONES', 'MANAGER', 7839, to_date('2-4-1981','dd-mm-yyyy'), 2975, null, 20);
insert into emp
values(7788, 'SCOTT', 'ANALYST', 7566, to_date('13-JUL-87','dd-mm-rr') - 85, 3000, null, 20);
insert into emp
values(7902, 'FORD', 'ANALYST', 7566, to_date('3-12-1981','dd-mm-yyyy'), 3000, null, 20);
insert into emp
values(7369, 'SMITH', 'CLERK', 7902, to_date('17-12-1980','dd-mm-yyyy'), 800, null, 20);
insert into emp
values(7499, 'ALLEN', 'SALESMAN', 7698, to_date('20-2-1981','dd-mm-yyyy'), 1600, 300, 30);
insert into emp
values(7521, 'WARD', 'SALESMAN', 7698, to_date('22-2-1981','dd-mm-yyyy'), 1250, 500, 30);
insert into emp
values(7654, 'MARTIN', 'SALESMAN', 7698, to_date('28-9-1981','dd-mm-yyyy'), 1250, 1400, 30);
insert into emp
values(7844, 'TURNER', 'SALESMAN', 7698, to_date('8-9-1981','dd-mm-yyyy'), 1500, 0, 30);
insert into emp
values(7876, 'ADAMS', 'CLERK', 7788, to_date('13-JUL-87', 'dd-mm-rr') - 51, 1100, null, 20);
insert into emp
values(7900, 'JAMES', 'CLERK', 7698, to_date('3-12-1981','dd-mm-yyyy'), 950, null, 30);
insert into emp
values(7934, 'MILLER', 'CLERK', 7782, to_date('23-1-1982','dd-mm-yyyy'), 1300, null, 10);
I tried using this query but it keeps telling me that name is an invalid identifier.
SELECT
(SELECT d.dname
FROM dept d
WHERE d.deptno = e.deptno) AS naam,
SUM(e.sal) AS sal
FROM
emp e
WHERE
sal < 20000
GROUP BY
naam;
Does anyone know what I'm doing wrong?
Use inner join and having
SELECT d.dname, sum(e.sal) sal
FROM dept d
INNER JOIN emp e on d.deptno = e.deptno
GROUP BY d.dname
HAVING sum(e.sal) < 20000

Find the number of employees in each department - SQL Oracle

I have two tables Emp and Dept and I am trying to display how many people work in each department along with their department name, but I can't get it to work. I have tried this select count(ename) as count from emp group by deptno; but the output I am getting is this :
COUNT
----------
6
5
3
But I also want to show the names for each of those departments. Here are my tables :
Empt:
CREATE TABLE EMP
(EMPNO NUMBER(4) NOT NULL,
ENAME VARCHAR2(10),
JOB VARCHAR2(9),
MGR NUMBER(4),
HIREDATE DATE,
SAL NUMBER(7, 2),
COMM NUMBER(7, 2),
DEPTNO NUMBER(2));
INSERT INTO EMP VALUES
(7369, 'SMITH', 'CLERK', 7902,
TO_DATE('17-DEC-1980', 'DD-MON-YYYY'), 800, NULL, 20);
INSERT INTO EMP VALUES
(7499, 'ALLEN', 'SALESMAN', 7698,
TO_DATE('20-FEB-1981', 'DD-MON-YYYY'), 1600, 300, 30);
INSERT INTO EMP VALUES
(7521, 'WARD', 'SALESMAN', 7698,
TO_DATE('22-FEB-1981', 'DD-MON-YYYY'), 1250, 500, 30);
INSERT INTO EMP VALUES
(7566, 'JONES', 'MANAGER', 7839,
TO_DATE('2-APR-1981', 'DD-MON-YYYY'), 2975, NULL, 20);
INSERT INTO EMP VALUES
(7654, 'MARTIN', 'SALESMAN', 7698,
TO_DATE('28-SEP-1981', 'DD-MON-YYYY'), 1250, 1400, 30);
INSERT INTO EMP VALUES
(7698, 'BLAKE', 'MANAGER', 7839,
TO_DATE('1-MAY-1981', 'DD-MON-YYYY'), 2850, NULL, 30);
INSERT INTO EMP VALUES
(7782, 'CLARK', 'MANAGER', 7839,
TO_DATE('9-JUN-1981', 'DD-MON-YYYY'), 2450, NULL, 10);
INSERT INTO EMP VALUES
(7788, 'SCOTT', 'ANALYST', 7566,
TO_DATE('09-DEC-1982', 'DD-MON-YYYY'), 3000, NULL, 20);
INSERT INTO EMP VALUES
(7839, 'KING', 'PRESIDENT', NULL,
TO_DATE('17-NOV-1981', 'DD-MON-YYYY'), 5000, NULL, 10);
INSERT INTO EMP VALUES
(7844, 'TURNER', 'SALESMAN', 7698,
TO_DATE('8-SEP-1981', 'DD-MON-YYYY'), 1500, 0, 30);
INSERT INTO EMP VALUES
(7876, 'ADAMS', 'CLERK', 7788,
TO_DATE('12-JAN-1983', 'DD-MON-YYYY'), 1100, NULL, 20);
INSERT INTO EMP VALUES
(7900, 'JAMES', 'CLERK', 7698,
TO_DATE('3-DEC-1981', 'DD-MON-YYYY'), 950, NULL, 30);
INSERT INTO EMP VALUES
(7902, 'FORD', 'ANALYST', 7566,
TO_DATE('3-DEC-1981', 'DD-MON-YYYY'), 3000, NULL, 20);
INSERT INTO EMP VALUES
(7934, 'MILLER', 'CLERK', 7782,
TO_DATE('23-JAN-1982', 'DD-MON-YYYY'), 1300, NULL, 10);
Dept:
CREATE TABLE DEPT
(DEPTNO NUMBER(2),
DNAME VARCHAR2(14),
LOC VARCHAR2(13) );
INSERT INTO DEPT VALUES (10, 'ACCOUNTING', 'NEW YORK');
INSERT INTO DEPT VALUES (20, 'RESEARCH', 'DALLAS');
INSERT INTO DEPT VALUES (30, 'SALES', 'CHICAGO');
INSERT INTO DEPT VALUES (40, 'OPERATIONS', 'BOSTON');
Please try:
select count(*) as count,dept.DNAME
from emp
inner join dept on emp.DEPTNO = dept.DEPTNO
group by dept.DNAME
A request to list "Number of employees in each department" or "Display how many people work in each department" is the same as "For each department, list the number of employees", this must include departments with no employees. In the sample database, Operations has 0 employees. So a LEFT OUTER JOIN should be used.
SELECT dept.name, COUNT(emp.empno) AS count
FROM dept
LEFT OUTER JOIN emp ON emp.deptno = dept.deptno
GROUP BY dept.name;
select count(e.empno), d.deptno, d.dname
from emp e, dep d
where e.DEPTNO = d.DEPTNO
group by d.deptno, d.dname;
Try the query below:
select count(*),d.dname from emp e , dept d where d.deptno = e.deptno
group by d.dname
SELECT d.DEPTNO
, d.dname
, COUNT(e.ename) AS count
FROM emp e
INNER JOIN dept d ON e.DEPTNO = d.deptno
GROUP BY d.deptno
, d.dname;
select d.dname
,count(e.empno) as count
from dept d
left outer join emp e
on e.deptno=d.deptno
group by d.dname;
Try to do this:
SQL> select dept,count(*) "no of emp" from employee group by dept;
DEPT no of emp
-------------------- ----------
HR 2
Account 2
Admin 3
select count(EMPNO),DNAME from EMP e join DEPT d on e.DEPTNO = d.DEPTNO group by DNAME ;

Select EMP with max SAL from each DEPT

I´m having a bad time with a SQL query. I´m using oracle default tables:
'EMP' TABLE
http://imageshack.us/photo/my-images/850/sinttuloxps.png/
AND
'DEPT' TABLE
http://imageshack.us/photo/my-images/19/assayp.png/
I wan´t to get the employee with the highest salary in each department.
I´m using SQLPLUS.
Thanks in advance!
ALSO CODE:
CREATE TABLE dept (
deptno numeric(2,0) NOT NULL,
dname character varying(14),
loc character varying(13),
CONSTRAINT dept_pkey PRIMARY KEY (deptno)
);
CREATE TABLE emp (
empno numeric(4,0) NOT NULL,
ename character varying(10),
job character varying(9),
mgr numeric(4,0),
hiredate date,
sal numeric(7,2),
comm numeric(7,2),
deptno numeric(2,0),
CONSTRAINT emp_pkey PRIMARY KEY (empno),
CONSTRAINT emp_deptno_fkey FOREIGN KEY (deptno) REFERENCES dept(deptno),
CONSTRAINT emp_mgr_fkey FOREIGN KEY (mgr) REFERENCES emp(empno)
);
INSERT INTO dept (deptno, dname, loc) VALUES (10, 'ACCOUNTING', 'NEW YORK');
INSERT INTO dept (deptno, dname, loc) VALUES (20, 'RESEARCH', 'DALLAS');
INSERT INTO dept (deptno, dname, loc) VALUES (30, 'SALES', 'CHICAGO');
INSERT INTO dept (deptno, dname, loc) VALUES (40, 'OPERATIONS', 'BOSTON');
insert into emp values (7839, 'KING' , 'PRESIDENT', NULL, to_date('17/11/81','dd/mm/yy') , 5000, NULL, 10);
insert into emp values (7566, 'JONES' , 'MANAGER' , 7839, to_date('02/04/81','dd/mm/yy') , 2975, NULL, 20);
insert into emp values (7902, 'FORD' , 'ANALYST' , 7566, to_date('03/12/81','dd/mm/yy') , 3000, NULL, 20);
insert into emp values (7369, 'SMITH' , 'CLERK' , 7902, to_date('17/12/80','dd/mm/yy') , 800, NULL, 20);
insert into emp values (7698, 'BLAKE' , 'MANAGER' , 7839, to_date('01/05/81','dd/mm/yy') , 2850, NULL, 30);
insert into emp values (7499, 'ALLEN' , 'SALESMAN' , 7698, to_date('20/02/81','dd/mm/yy') , 1600, 300, 30);
insert into emp values (7521, 'WARD' , 'SALESMAN' , 7698, to_date('22/02/81','dd/mm/yy') , 1250, 500, 30);
insert into emp values (7654, 'MARTIN' , 'SALESMAN' , 7698, to_date('28/09/81','dd/mm/yy') , 1250, 1400, 30);
insert into emp values (7782, 'CLARK' , 'MANAGER' , 7839, to_date('09/06/81','dd/mm/yy') , 2450, NULL, 10);
insert into emp values (7788, 'SCOTT' , 'ANALYST' , 7566, to_date('09/12/82','dd/mm/yy') , 3000, NULL, 20);
insert into emp values (7844, 'TURNER' , 'SALESMAN' , 7698, to_date('08/09/81','dd/mm/yy') , 1500, 0, 30);
insert into emp values (7876, 'ADAMS' , 'CLERK' , 7788, to_date('12/01/83','dd/mm/yy') , 1100, NULL, 20);
insert into emp values (7900, 'JAMES' , 'CLERK' , 7698, to_date('03/12/81','dd/mm/yy') , 950, NULL, 30);
insert into emp values (7934, 'MILLER' , 'CLERK' , 7782, to_date('23/01/82','dd/mm/yy') , 1300, NULL, 10);
You can also use the analytical RANK() function:
SELECT * FROM (
SELECT
Dept.DeptNo,
Dept.DName,
Emp.EName,
Emp.Sal,
RANK() OVER (PARTITION BY Dept.DeptNo ORDER BY Emp.Sal DESC) AS DeptSalRank
FROM Emp
INNER JOIN Dept ON Emp.DeptNo = Dept.DeptNo
)
WHERE DeptSalRank = 1
Classic greatest-n-per-group query. Here is what you want:
select dept.dname, emp.empno, emp.ename, emp.sal
from emp
inner join dept on emp.deptno = dept.deptno
inner join
(
select emp.deptno, max(emp.sal) sal
from emp
group by emp.deptno
) ss on emp.deptno = ss.deptno and emp.sal = ss.sal
order by emp.sal desc
Here is a working fiddle: http://sqlfiddle.com/#!4/7147b/6
Additionally, you might want to checkout a different approach. Look here (SQL Select only rows with Max Value on a Column) to see an interesting answer on the topic.
The following query will omit duplicate values
SELECT DEPTNO, MAX(SAL) FROM EMP GROUP BY DEPTNO;
The following query will include the duplicate values
SELECT * FROM EMP WHERE (DEPTNO,SAL) IN
( SELECT DEPTNO, MAX(SAL) FROM EMP GROUP BY DEPTNO)
As short as the question: SELECT DeptID, MAX(Salary) FROM Employees GROUP BY DeptID
Tested. Here is the query:
Select outemp.Employee_ID, outemp.First_Name, outemp.Last_Name
From Hr.Employees outemp,
HR.Departments outdept,
(Select Max(e.salary) maxsal, D.Department_ID Dept_ID From HR.EMPLOYEES e, HR.Departments d
WHERE e.Department_ID = d.Department_ID
Group By d.Department_ID) DummyTable
where outemp.Department_ID = outdept.Department_ID
AND outdept.Department_ID = DummyTable.Dept_ID
AND outemp.Salary = DummyTable.Maxsal
list of top 10 highest paid employee detail
(SELECT *, RANK() OVER (ORDER BY Emp.Sal DESC)AS DeptSalRank
FROM Emp INNER JOIN Dept ON Emp.DeptNo = Dept.DeptNo) LIMIT 10;