Getting data from two tables? - sql

I am trying to get data from two different table and put into on statement but its not working. This is what I am looking to get as a complete statement: I want the query to display the dname, loc, Number of People. I am having a problems with the sub query.
SQL> select dname, loc from dept where ename in (count(ename) AS Number_of_People from emp);
select dname, loc from dept where ename in (count(ename) AS Number_of_People from emp)
*
ERROR at line 1:
ORA-00934: group function is not allowed here
SQL>
Table emp
SQL> select empno, ename, job, hiredate, deptno from emp;
EMPNO ENAME JOB HIREDATE DEPTNO
---------- ---------- --------- --------- ----------
7839 KING PRESIDENT 17-NOV-81 10
7698 BLAKE MANAGER 01-MAY-81 30
7782 CLARK MANAGER 09-JUN-81 10
7566 JONES MANAGER 02-APR-81 20
7654 MARTIN SALESMAN 28-SEP-81 30
7499 ALLEN SALESMAN 20-FEB-81 30
7844 TURNER SALESMAN 08-SEP-81 30
7900 JAMES CLERK 03-DEC-81 30
7521 WARD SALESMAN 22-FEB-81 30
7902 FORD ANALYST 03-DEC-81 20
7369 SMITH CLERK 17-DEC-80 20
EMPNO ENAME JOB HIREDATE DEPTNO
---------- ---------- --------- --------- ----------
7788 SCOTT ANALYST 09-DEC-82 20
7876 ADAMS CLERK 12-JAN-83 20
7934 MILLER CLERK 23-JAN-82 10
14 rows selected.
SQL>
Table dept
SQL> select * from dept;
DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
SQL>

Are you trying to achieve something like this?
select dname, loc, (select count(ename) from emp where DEPTNO = dept.deptno) as Number_of_people
from dept;

I'm not sure what you're trying to do, but something that sticks out is that you probably need to use a select in your subquery. Try:
select dname, loc
from dept
where ename in (select count(ename) AS Number_of_People from emp);

Try this
select dept.dname, dept.loc,count(*)
from emp
join dept on emp.deptNo=dept.deptno
group by dept.dname,dept.loc

Related

SQL join without data loss

I want a select that naturally joins 2 tables. Afer joining table A with table B the new temporary table C doesn't contain the row of table A if the primary key of this row is not used in any rows of table B. I understand why that happens, but I want the row also in table C.
Example
select deptno, dname, loc, count(deptno) empcount, round(avg(sal),2) avgsal
from dept natural join emp
group by deptno, dname, loc
Result:
DEPTNO DNAME LOC EMPCOUNT AVGSAL
---------- -------------- ------------- ---------- ----------
20 RESEARCH DALLAS 5 2175
10 ACCOUNTING NEW YORK 3 2916.67
30 SALES CHICAGO 6 1566.67
What I want:
DEPTNO DNAME LOC EMPCOUNT AVGSAL
---------- -------------- ------------- ---------- ----------
20 RESEARCH DALLAS 5 2175
10 ACCOUNTING NEW YORK 3 2916.67
30 SALES CHICAGO 6 1566.67
40 OPERATIONS BOSTON 0 0
Table dept (A):
DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
Table emp (B):
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- --------- ---------- ---------- ----------
7369 SMITH CLERK 7902 17-DEC-80 800 20
7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30
7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30
7566 JONES MANAGER 7839 02-APR-81 2975 20
7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30
7698 BLAKE MANAGER 7839 01-MAY-81 2850 30
7782 CLARK MANAGER 7839 09-JUN-81 2450 10
7788 SCOTT ANALYST 7566 19-APR-87 3000 20
7839 KING PRESIDENT 17-NOV-81 5000 10
7844 TURNER SALESMAN 7698 08-SEP-81 1500 0 30
7876 ADAMS CLERK 7788 23-MAY-87 1100 20
7900 JAMES CLERK 7698 03-DEC-81 950 30
7902 FORD ANALYST 7566 03-DEC-81 3000 20
7934 MILLER CLERK 7782 23-JAN-82 1300 10
select deptno, dname, loc, count(deptno) empcount, round(avg(sal),2) avgsal
from dept
LEFT join emp
group by deptno, dname, loc
Is this what you are looking at? Check the output...
According to http://docs.oracle.com/javadb/10.8.3.0/ref/rrefsqljnaturaljoin.html you can do an outer natural join like so:
The following example is similar to the one above, but it also preserves
unmatched rows from the first (left) table:
SELECT * FROM COUNTRIES NATURAL LEFT JOIN CITIES
So you would do:
select deptno, dname, loc, count(deptno) empcount, round(avg(sal),2) avgsal
from dept natural left join emp
group by deptno, dname, loc
Use left join instead fo natural join.
select deptno, dname, loc, count(deptno) empcount, round(coalesce(avg(sal), 0),2) avgsal
from dept left join emp
group by deptno, dname, loc
Thanks a lot, it was the outer join I was looking for.
So here's the sql command that deliveres the result I was looking for:
SQL99-Syntax:
select deptno, dname, loc, nvl(ecount,0) empcount, nvl(round(avg(sal),2),0) avgsal
from dept left join emp using(deptno)
left join (select deptno, count(deptno) ecount
from emp
group by deptno) using(deptno)
group by deptno, dname, loc, ecount
Standard SQL-Syntax:
select d.deptno, d.dname, d.loc, nvl(n.ecount,0) empcount, nvl(round(avg(e.sal),2),0) avgsal
from dept d, emp e, (select deptno, count(deptno) ecount
from emp
group by deptno) n
where d.deptno = e.deptno (+)
and n.deptno (+) = e.deptno
group by d.deptno, d.dname, d.loc, n.ecount
The column empcount is 0 if there are no employees in the department. In the other solutions it was 1 because there was one row for each department after the outer join in the temporary table.

ORA-00913: too many values error when I run a query in SQL*Plus

I am trying to get the dname, loc, and count the ename's, plus I want to include the sal from the table. Can someone tell me what I am doing wrong.
Heres my statement with the error I get
SQL> select dname, loc, (select count(ename), sal from emp where DEPTNO = dept.deptno) as Number_of_people from dept;
select dname, loc, (select count(ename), sal from emp where DEPTNO = dept.deptno) as Number_of_people from dept
*
ERROR at line 1:
ORA-00913: too many values
SQL>
Heres my table
SQL> select empno, ename, job, hiredate, sal from emp;
EMPNO ENAME JOB HIREDATE SAL
---------- ---------- --------- --------- ----------
7839 KING PRESIDENT 17-NOV-81 5000
7698 BLAKE MANAGER 01-MAY-81 2850
7782 CLARK MANAGER 09-JUN-81 2450
7566 JONES MANAGER 02-APR-81 2975
7654 MARTIN SALESMAN 28-SEP-81 1250
7499 ALLEN SALESMAN 20-FEB-81 1600
7844 TURNER SALESMAN 08-SEP-81 1500
7900 JAMES CLERK 03-DEC-81 950
7521 WARD SALESMAN 22-FEB-81 1250
7902 FORD ANALYST 03-DEC-81 3000
7369 SMITH CLERK 17-DEC-80 800
EMPNO ENAME JOB HIREDATE SAL
---------- ---------- --------- --------- ----------
7788 SCOTT ANALYST 09-DEC-82 3000
7876 ADAMS CLERK 12-JAN-83 1100
7934 MILLER CLERK 23-JAN-82 1300
14 rows selected.
SQL>
Heres the second table
SQL> select * from dept;
DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
SQL>
To get number of people and total Salary, try this...
select dept.dname, dept.loc,
count(emp.ename) as Number_of_people, sum(emp.sal) as Total_Salary
from emp
join dept on emp.DEPTNO = dept.deptno
group by dept.dname,dept.loc
You can get other things as well
select dept.dname, dept.loc,
count(emp.ename) as Number_of_people,
sum(emp.sal) as Total_Salary,
avg(emp.sal) as Average_salary,
min(emp.hiredate) as First_dept_hire,
max(emp.hireDate) as Last_dept_hire
from emp
join dept on emp.DEPTNO = dept.deptno
group by dept.dname,dept.loc
The scalar (inline) cursor can only have only one value in its projection.
If you want to have more than one value, use a join and aggregate all the values, as Sparky suggests.

Average the sal then sort in descending order

I want to list all the employees that make more than the average salary. I'm alittle lost on this one. I need to add up all the salary's then average them out and only display the ones that make more than the average. I need alot of help on this one.
My query that doesnt work
SQL> select empno, ename, job, hiredate, sal, deptno from emp where sal avg(sal);
select empno, ename, job, hiredate, sal, deptno from emp where sal avg(sal)
*
ERROR at line 1:
ORA-00920: invalid relational operator
SQL>
Table
SQL> select empno, ename, job, hiredate, sal, deptno from emp;
EMPNO ENAME JOB HIREDATE SAL DEPTNO
---------- ---------- --------- --------- ---------- ----------
7839 KING PRESIDENT 17-NOV-81 5000 10
7698 BLAKE MANAGER 01-MAY-81 2850 30
7782 CLARK MANAGER 09-JUN-81 2450 10
7566 JONES MANAGER 02-APR-81 2975 20
7654 MARTIN SALESMAN 28-SEP-81 1250 30
7499 ALLEN SALESMAN 20-FEB-81 1600 30
7844 TURNER SALESMAN 08-SEP-81 1500 30
7900 JAMES CLERK 03-DEC-81 950 30
7521 WARD SALESMAN 22-FEB-81 1250 30
7902 FORD ANALYST 03-DEC-81 3000 20
7369 SMITH CLERK 17-DEC-80 800 20
EMPNO ENAME JOB HIREDATE SAL DEPTNO
---------- ---------- --------- --------- ---------- ----------
7788 SCOTT ANALYST 09-DEC-82 3000 20
7876 ADAMS CLERK 12-JAN-83 1100 20
7934 MILLER CLERK 23-JAN-82 1300 10
14 rows selected.
You are getting the invalid relational operator error because you nave omitted the less than
sign in your query. Please learn to read the documentation.
Beyond that, you need to write a sub-query to calculate the average salary. So your query should look like this:
select empno, ename, job, hiredate, sal, deptno
from emp
where sal > (select avg(sal) from emp)
order by sal desc;
Doesn't Oracle support windowed functions? I'm not sure whether you can use a windowed function directly in the WHERE clause, but at least you can derive a table from a query that uses it and then reference the corresponding column in a condition:
SELECT
empno, ename, job, hiredate, sal, deptno
FROM (
SELECT
empno, ename, job, hiredate, sal, deptno
AVG(sal) OVER () AS avgsal
FROM emp
) s
WHERE sal > avgsal

I want to choose hiredate between '20-FEB-81' AND '01-MAY-81'

I want the names of the employees, job, hiredate between '20-FEB-81' AND '01-MAY-81', and in ascending order
query I ran with error
SQL> select ename, job, hiredate where hiredate between '20-FEB-81' AND '01-MAY-81' from emp;
select ename, job, hiredate where hiredate between '20-FEB-81' AND '01-MAY-81' from emp
*
ERROR at line 1:
ORA-00923: FROM keyword not found where expected
SQL>
My table
SQL> select empno, ename, job, hiredate, sal from emp;
EMPNO ENAME JOB HIREDATE SAL
---------- ---------- --------- --------- ----------
7839 KING PRESIDENT 17-NOV-81 5000
7698 BLAKE MANAGER 01-MAY-81 2850
7782 CLARK MANAGER 09-JUN-81 2450
7566 JONES MANAGER 02-APR-81 2975
7654 MARTIN SALESMAN 28-SEP-81 1250
7499 ALLEN SALESMAN 20-FEB-81 1600
7844 TURNER SALESMAN 08-SEP-81 1500
7900 JAMES CLERK 03-DEC-81 950
7521 WARD SALESMAN 22-FEB-81 1250
7902 FORD ANALYST 03-DEC-81 3000
7369 SMITH CLERK 17-DEC-80 800
EMPNO ENAME JOB HIREDATE SAL
---------- ---------- --------- --------- ----------
7788 SCOTT ANALYST 09-DEC-82 3000
7876 ADAMS CLERK 12-JAN-83 1100
7934 MILLER CLERK 23-JAN-82 1300
14 rows selected.
SQL>
The WHERE part goes after the FROM part.
select ename, job, hiredate
from emp
where hiredate between '20-FEB-81' AND '01-MAY-81'
Note that your date literals may not always work if the NLS settings change. It is highly recommended to use to_date() instead.
select ename, job, hiredate
from emp
where hiredate between to_date('20-FEB-81', 'DD-MON-RR') AND to_date('01-MAY-81', 'DD-MON-RR')
But this is still subject to language settings problems, better not use month names at all:
select ename, job, hiredate
from emp
where hiredate between to_date('20-02-81', 'DD-MM-RR') AND to_date('01-05-81', 'DD-MM-RR')

I want to get all jobs that are in dept 30 including the location

I want to get all jobs that are in dept 30 including the location
SQL> select deptno,job from emp where deptno =30 (select loc from dept);
select deptno,job from emp where deptno =30 (select loc from dept)
*
ERROR at line 1:
ORA-00933: SQL command not properly ended
SQL>
Table emp
SQL> select empno, ename, job, hiredate, deptno from emp;
EMPNO ENAME JOB HIREDATE DEPTNO
---------- ---------- --------- --------- ----------
7839 KING PRESIDENT 17-NOV-81 10
7698 BLAKE MANAGER 01-MAY-81 30
7782 CLARK MANAGER 09-JUN-81 10
7566 JONES MANAGER 02-APR-81 20
7654 MARTIN SALESMAN 28-SEP-81 30
7499 ALLEN SALESMAN 20-FEB-81 30
7844 TURNER SALESMAN 08-SEP-81 30
7900 JAMES CLERK 03-DEC-81 30
7521 WARD SALESMAN 22-FEB-81 30
7902 FORD ANALYST 03-DEC-81 20
7369 SMITH CLERK 17-DEC-80 20
EMPNO ENAME JOB HIREDATE DEPTNO
---------- ---------- --------- --------- ----------
7788 SCOTT ANALYST 09-DEC-82 20
7876 ADAMS CLERK 12-JAN-83 20
7934 MILLER CLERK 23-JAN-82 10
14 rows selected.
Table dept
SQL> select * from dept;
DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
SQL>
You need to join the two tables
SELECT deptno,
e.job,
d.loc
FROM emp e
JOIN dept d USING (deptno)
WHERE deptno = 30
SELECT empno, ename, job, hiredate, emp.deptno, location FROM emp
LEFT JOIN dept ON emp.deptno = dept.deptno
WHERE emp.deptno = 30