I have 4 tables, EMPLOYEE, DRIVER, TRIP and TRIPLEG
EMPLOYEE table has Name which I want to extract and show with MAX count, has E# which is shared with DRIVER
DRIVER table has L#(licence number) which is common with TRIP
TRIP table has T#(trip number) which is common with TRIPLEG
I'm trying to find the max number of tripleg a driver has done(In this case driver with licence number 10002:
SELECT MAX(COUNT(TRIPLEG.LEG#))
FROM TRIP, TRIPLEG
ON TRIP.T# = TRIPLEG.T#
WHERE TRIP.L# = 10002
GROUP BY TRIP.T#
COUNT(TRIPLEG.LEG#) gives me https://i.imgur.com/AYAovov.png,
so I did the above MAX(COUNT(TRIPLEG.LEG#)) which gives me this: https://i.imgur.com/alCFlO3.png
I'm unable to proceed as I tried SELECTING more columns(TRIP.T#) like
SELECT TRIP.T#, MAX(COUNT(TRIPLEG.LEG#))
FROM TRIP, TRIPLEG
ON TRIP.T# = TRIPLEG.T#
WHERE TRIP.L# = 10002
GROUP BY TRIP.T#
Gives me an error: ORA-00937: not a single-group group function
Any advice? Need to be able to start small and selecting before I can join more tables to get the Employee name displayed beside the MAX tripleg count
Thanks in advance
Essentially I want something like: (only 1 row, which is the MAX triplegs done (5))
NAME MAX(COUNT(TRIPLEG.LEG#))
-----------------------------------
BOB 5
I don't have your table so I'll use Scott's EMP and DEPT (as you use Oracle, so I presume you're familiar with them).
This works:
SQL> select d.dname, count(e.empno) cnt
2 from emp e join dept d on e.deptno = d.deptno
3 where d.deptno in (10, 20)
4 group by d.dname;
DNAME CNT
-------------- ----------
ACCOUNTING 3
RESEARCH 5 --> MAX count is this
SQL>
Nested count works if there are no other columns in SELECT column list (you already know that), and it returns desired value:
SQL> select max(count(e.empno)) cnt
2 from emp e join dept d on e.deptno = d.deptno
3 where d.deptno in (10, 20)
4 group by d.dname;
CNT
----------
5
SQL>
But, this won't work (you know that too):
select d.dname, max(count(e.empno)) cnt
from emp e join dept d on e.deptno = d.deptno
where d.deptno in (10, 20)
group by d.dname;
To fix it, use CTE (Common Table Expression a.k.a. the WITH factoring clause) or an inline view; I'll show you the first option, with yet another addition: I'll rank counts and find the "highest" one, and use it later to select only desired row.
SQL> with tcnt as
2 (select d.deptno,
3 d.dname,
4 count(e.empno) cnt,
5 rank() over (order by count(e.empno) desc) rnk --> rank them DESC
6 from emp e join dept d on e.deptno = d.deptno
7 where d.deptno in (10, 20)
8 group by d.dname, d.deptno
9 )
10 select t.deptno, t.dname, t.cnt
11 from tcnt t
12 where rnk = 1; --> fetch only row(s) with highest rank
DEPTNO DNAME CNT
---------- -------------- ----------
20 RESEARCH 5
SQL>
Finally, add some more columns from other tables:
SQL> with tcnt as
2 (select d.deptno,
3 d.dname,
4 count(e.empno) cnt,
5 rank() over (order by count(e.empno) desc) rnk
6 from emp e join dept d on e.deptno = d.deptno
7 where d.deptno in (10, 20)
8 group by d.dname, d.deptno
9 )
10 select t.deptno, t.dname, t.cnt, e.ename, e.job
11 from tcnt t join emp e on e.deptno = t.deptno
12 where rnk = 1;
DEPTNO DNAME CNT ENAME JOB
---------- -------------- ---------- ---------- ---------
20 RESEARCH 5 SMITH CLERK
20 RESEARCH 5 JONES MANAGER
20 RESEARCH 5 SCOTT ANALYST
20 RESEARCH 5 ADAMS CLERK
20 RESEARCH 5 FORD ANALYST
SQL>
Based on your tables to find the max number of tripleg a driver has done(In this case driver with licence number 10002:
Select a.tripno, max(a.trips)
From
(Select Trip.T# as tripno, count(tripleg.leg#) as trips
From tripleg join trip on tripleg.T# = trip.T#
where trip.L# = 10002
Group by tripno
) a
Group by a.tripno
Related
I've run into an error I've never seen before while trying to learn SQL where it is saying that my group by function is nested too deeply? Any ideas on how to fix this code would be greatly appreciated. I am trying to find the division with the most employees.
Tables:
division(DID, dname, managerID)
employee(empid, name, salary, DID)
Code:
select dname
from division
where did in (select did from employee group by did having max(count(empid)))
I don't have your tables, but Scott's sample schema contains similar tables - dept (departments) and emp (employees who work in these departments).
How many employees work in each department?
SQL> select deptno, count(*)
2 from emp
3 group by deptno
4 order by 2 desc;
DEPTNO COUNT(*)
---------- ----------
30 6 --> this is what you want, it has the most employees
20 5
10 3
Which department is it?
SQL> select * from dept order by deptno;
DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO --> it's SALES
40 OPERATIONS BOSTON
SQL>
This is what you tried: not that it won't work (Oracle doesn't let you), syntax is wrong. having clause should be something like having count(*) = 25, not just your wishes comes true (having max(count(*)) which reads as "give me department that has maximum count of employees").
SQL> select dname
2 from dept
3 where deptno in (select deptno from emp
4 group by deptno
5 having max(count(empno))
6 );
having max(count(empno))
*
ERROR at line 5:
ORA-00935: group function is nested too deeply
SQL>
So, what can we do about it? A simple option is to rank departments by number of employees:
SQL> select deptno,
2 count(*) cnt,
3 rank() over (order by count(*) desc) rnk
4 from emp
5 group by deptno;
DEPTNO CNT RNK
---------- ---------- ----------
30 6 1 --> department 30 ranks as the highest
20 5 2
10 3 3
SQL>
The rest is easy: use that query as a subquery (or a CTE, as I did), and select the one that ranks the highest:
SQL> with temp as
2 (select deptno,
3 count(*) cnt,
4 rank() over (order by count(*) desc) rnk
5 from emp
6 group by deptno
7 )
8 select d.dname
9 from dept d join temp t on t.deptno = d.deptno
10 where t.rnk = 1; --> the highest rank
DNAME
--------------
SALES
SQL>
SALES it is.
I trying to use oracle order by with select statement but it causes an Exception:
ORA-01791: not a SELECTed expression.
select distinct usermenu.menuname
from usermenu, userpermission
where userpermission.menuno = usermenu.menuno
and userpermission.userno = 1
order by userpermission.menuno;
When there's DISTINCT or an aggregate function in the SELECT statement's column list, ORDER BY a column which isn't part of the SELECT column list won't work.
Here's an example, based on Scott's schema.
This works OK, although D.LOC isn't selected:
SQL> select d.dname, e.ename
2 from dept d join emp e on e.deptno = d.deptno
3 order by d.loc;
DNAME ENAME
-------------- ----------
SALES BLAKE
SALES TURNER
SALES ALLEN
SALES MARTIN
SALES WARD
SALES JAMES
RESEARCH SCOTT
RESEARCH JONES
RESEARCH SMITH
RESEARCH ADAMS
RESEARCH FORD
ACCOUNTING KING
ACCOUNTING MILLER
ACCOUNTING CLARK
14 rows selected.
Now, add DISTINCT - basically, that's what you have:
SQL> select distinct d.dname, e.ename
2 from dept d join emp e on e.deptno = d.deptno
3 order by d.loc;
order by d.loc
*
ERROR at line 3:
ORA-01791: not a SELECTed expression
The same goes for aggregate functions, such as COUNT:
SQL> select d.dname, e.ename, count(*)
2 from dept d join emp e on e.deptno = d.deptno
3 group by d.dname, e.ename
4 order by d.loc;
order by d.loc
*
ERROR at line 4:
ORA-00979: not a GROUP BY expression
SQL>
So, what to do? Order by something else. Alternatively, use the current query as an inline view, join it with the table that contains the column you'd want to order the result by and it'll work:
SQL> select x.dname, x.ename
2 from (select distinct d.dname, e.ename
3 from dept d join emp e on e.deptno = d.deptno
4 ) x
5 join dept d1 on d1.dname = x.dname
6 order by d1.loc;
DNAME ENAME
-------------- ----------
SALES TURNER
SALES JAMES
SALES BLAKE
SALES WARD
SALES MARTIN
SALES ALLEN
RESEARCH SMITH
RESEARCH FORD
RESEARCH ADAMS
RESEARCH SCOTT
RESEARCH JONES
ACCOUNTING MILLER
ACCOUNTING KING
ACCOUNTING CLARK
14 rows selected.
SQL>
I have the following Table.
STAFF
STAFFNO STAFFNAME DESIGNATI SALARY DEPTNO
---------- ---------- --------- ---------- ----------
1000 Rajesh Manager 35000 1
1001 Manoj Caretaker 7420.35 1
1002 Swati HR 22500 3
1003 Suresh HR 23400 3
1004 Najim Mangager 17200 2
1006 Ritesh Prgrmr 23500 2
1005 Nisha Prgrmr 24852 1
1007 Rajib Security 6547 3
1008 Neeraj Prgrmr 17300 1
1009 Dushant Prgrmr 16500 1
1010 Pradyut Manager 26300 2
1011 Manisha Prgrmr 21500 2
1012 Janak Security 8500 2
Now I want to run a query on oracle (SQL*Plus) in which I can retrieve the details of those employees who works in a department having 5 or more head count.(e.g. deptno. 1 and deptno. 2 have 5 employees working in them)
Can you help me with the Oracle query to retrieve that? Thanks in advance.
You need create a sub query or perform a JOIN.
With a JOIN first you need to know what department has more that 5 employees.
SELECT DEPTNO
FROM STAFF
GROUP BY DEPTNO
HAVING COUNT(*) >= 5
Now you join both result
SELECT S.*
FROM STAFF S
JOIN ( SELECT DEPTNO
FROM STAFF
GROUP BY DEPTNO
HAVING COUNT(*) >= 5 ) F
ON S.DEPTNO = F.DEPTNO
Subquery version:
SELECT S.*
FROM STAFF S
WHERE S.DEPTNO IN ( SELECT DEPTNO
FROM STAFF
GROUP BY DEPTNO
HAVING COUNT(*) >= 5 )
If you want the employee detail, then you actually want an analytic function:
select s.*
from (select s.*, count(*) over (partition by deptno) as deptcnt
from staff
) s
where deptcnt >= 5;
It should be like this
SELECT * FROM STAFF WHERE DEPTNO IN
(SELECT DEPTNO FROM STAFF GROUP BY DEPTNO HAVING COUNT(*)>4)
Here it is using a join (because no one has) it may allow you to change your BI rules easier....
SELECT S.*
FROM STAFF S
LEFT JOIN (
SELECT DEPTNO, COUNT(*) AS C
FROM STAFF
GROUP BY DEPTNO
) AS D_COUNTS ON S.DEPTNO = D_COUNT.DEPTNO
WHERE D_COUNTS.C >= 5
or as a CTE
WITH D_COUNTS AS
(
SELECT DEPTNO, COUNT(*) AS C
FROM STAFF
GROUP BY DEPTNO
)
SELECT S.*
FROM STAFF S
LEFT JOIN D_COUNTS ON S.DEPTNO = D_COUNT.DEPTNO
WHERE D_COUNTS.C >= 5
I guess messed up the joins...
Single DEPT has many LOCations, every DEPT should have a sum of its EMPs. I need to show DISTINCT LOCs, number of LOCs per DEPT and sum of EMPS in each DEPT - without dividing the locations.
With tables DEPT & EMP like this:
SELECT DEPTNO, DNAME, LOC FROM DEPT;
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
50 NONE DALLAS
select ENAME, DEPTNO from EMP;
SMITH 20
ALLEN 30
WARD 30
JONES 20
MARTIN 30
BLAKE 30
CLARK 10
SCOTT 20
KING 10
TURNER 30
ADAMS 20
JAMES 30
FORD 20
MILLER 10
CURT 40
Can't properly add the below subquery into my WITH... clause below. Need to select how many DEPTNO's exists for each LOC plus give a number of EMP's in each DEPT like here (plus location number) - it should use 2 different kinds of summaries in:
select e.deptno, count(e.deptno) from emp e
group by e.deptno;
10 3
20 5
30 6
40 1
Here is what I did:
WITH workers_per_dept as
(SELECT
d.LOC LOC,
d.deptno DEPTNO,
count(e.empno) EMP_NUMBER
FROM dept d
LEFT OUTER JOIN emp e ON (e.deptno = d.deptno)
GROUP BY d.LOC,d.deptno
ORDER BY d.deptno)
select
d.LOC LOCATION,
count(d.LOC) LOCATIONS_PER_DEPT,
workers_per_dept.EMP_NUMBER
from DEPT d, workers_per_dept
WHERE d.LOC = workers_per_dept.LOC
GROUP BY d.LOC, workers_per_dept.EMP_NUMBER
ORDER BY 1;
I receive this (should be groupped by LOC with):
BOSTON 1 1
CHICAGO 1 6
DALLAS 2 0
DALLAS 2 5
NEW YORK 1 3
(result should have not repeated LOC's - 'DALLAS 2 0' should be skipped)
Here is the query. You need to group by location and count distinct occurrences of Dept's in each group:
select d.loc,
count(distinct d.deptno) depts,
count(e.ename) emps
from dept d
left join emp e on d.deptno = e.deptno
group by d.loc
Stupid me... but finally did it myself
it was so easy...
SELECT d.LOC LOCATION,
(select count(d.LOC) FROM DEPT l WHERE l.LOC=d.LOC) LOCS,
(select count(e.deptno) FROM EMP e WHERE e.DEPTNO = d.DEPTNO) EMPS
FROM DEPT d;
Thanks for help!!!
I have an emp table like this
EMPNO | JOB | DEPTNO
_____________________
1 | A | 10
2 | B | 20
3 | C | 10
4 | A | 20
I want to write a query to List the jobs common to department 10 and 20.
So the output as per the data provided should be
A
which is common to both deptno 10 and 20
I am trying this but it doesn't give me any output.
select job, deptNo from emp group by job having deptno = 20 and deptno = 10; /*6*/
Try this
select job
from emp e1
where e1.deptno = 10
and exists ( select 1
from emp e2
where e2.deptno = 20
and e1.job = e2.job
)
group by job;
You can use an aggregate function in the HAVING clause with the condition you need:
SELECT job
FROM emp
GROUP BY job
HAVING COUNT(CASE WHEN deptNo IN (10, 20) THEN 1 END) = 2
The fields can't be both values at the same time. Use an Or instead of And. Also, the Having doesn't quite make sense, just use Where.
select job, deptNo
from emp
Where deptno = 20
Or deptno = 10
group by job
You can also use an In, which would have the same effect as an Or:
select job, deptNo
from emp
Where deptno In (10, 20)
group by job
Edit: You can do this to get the Jobs that have both values:
Select Distinct a.job
From emp a
Where DeptNo = 10
And Exists
(
Select 1
From Emp b
Where a.Job = b.Job
And b.deptNo = 20
)