How do I display rows from a max count? - sql

I want to return all the data, from max count query with hospital that has most number of patients. What I seem to be getting when I try to nest queries is display of all rows of hospital data. I've tried to look at similar questions in stack overflow and other sites it seems to be a simple query to do but i am not getting it.
select max(highest_hospital) as max_hospital
from (select count(hospital) as highest_hospital
from doctor
group by hospital)
highest_hospital
-------------
3
Doc ID Doctor Patient Hospital Medicine Cost
------ ------- ------ --------- ------ --------
1 Jim Bob Patient1 Town 1 Medicine 1 4000
2 Janice Smith Patient2 Town 2 Medicine 3 3000
3 Harold Brown Patient3 Town 2 Medicine 5 2000
4 Larry Owens Patient4 Town 2 Medicine 6 3000
5 Sally Brown Patient5 Town 3 Medicine 7 4000
6 Bob Jim Patient6 Town 4 Medicine 8 6000
Outcome should be return of 3 rows
Doc ID Doctor Patient Hospital Medicine Cost
------ ------- ------ --------- ------ --------
2 Janice Smith Patient2 Town 2 Medicine 3 3000
3 Harold Brown Patient3 Town 2 Medicine 5 2000
4 Larry Owens Patient4 Town 2 Medicine 6 3000

You can use window functions:
select d.*
from (select d.*, max(hospital_count) over () as max_hospital_count
from (select d.*, count(*) over (partition by hospital) as hospital_count
from doctor d
) d
) d
where hospital_count = max_hospital_count;
Edit:
Using GROUP BY is a pain. If you are only looking for a single hospital (even when there are ties), then in Oracle 12C you can do:
select d.*
from doctor d
where d.hospital = (select d2.hospital
from doctor d2
group by d2.hospital
order by count(*) desc
fetch first 1 row only
);
You can do this in earlier versions of Oracle using an additional subquery.

Related

How to not return a value of 0 when data does not exist in table, SQLPLUS

I have two tables, table A and B, and I am counting the number of occurences of a data type from table A,
ENAME SALES
---------- ----------
Wilson 0
Fox 1
Wang 2
Green 1
Fox 0
Phillips 2
Loftus 0
Smith 2
Smith 3
Wolf 2
Jones 1
Liu 0
Where when the sales count is 0, the ename does not exist in table B at all.
How would I go about removing the 0 count? I'm trying to get the return to look like this:
ENAME SALES
---------- ----------
Wilson
Fox 1
Wang 2
Green 1
Fox
Phillips 2
Loftus
Smith 2
Smith 3
Wolf 2
Jones 1
Liu
One method uses case, another nullif():
select ename, nullif(sales, 0) as sales
from t;
If this is an aggregation query:
select ename, nullif(count(*), 0) as sales
from t
group by ename;

SQL SELECT query to pull data from tables to calculate a sum

I have four tables in a database, what I want to do is essentially list the employee number, name department number of any projects they are working on and the total hours that they spend working on projects.
I'm trying to do this all as one single SELECT statement, but am having trouble getting it to work with Oracle SQL. My latest attempt has been
SELECT EMPLOYEE.E#, EMPLOYEE.NAME, SUM(WORKSON.HOURS)
FROM EMPLOYEE JOIN WORKSON ON EMPLOYEE.E#=WORKSON.E#
GROUP BY EMPLOYEE.E#;
Which isn't even the complete statement, and gives me the error:
ERROR at line 1:
ORA-00979: not a GROUP BY expression
What can I do to complete the statement to also include the department number and what should I be doing? Should I be using a join for this? or should I be incorporating another SELECT statement within a WHERE clause?
The tables are as follows:
EMPLOYEE:
SQL> SELECT * FROM EMPLOYEE;
E# NAME DOB S SALARY SUPER D#
----- ------------------ ----------- -- ------ -------- ---
00100 Albert 13-OCT-65 M 186.5
00110 Alvin 13-OCT-77 M 156.4 00100 1
00120 Alice 17-JUN-73 F 156.5 00100 2
00150 Bob 02-JUL-60 M 166.4 00100 3
00200 Carl 02-FEB-67 M 156.3 00100 4
00250 Douglass 14-APR-83 M 156.4 00100 5
00101 Peter 13-NOV-76 M 85.2 00110 1
00103 Ami 12-SEP-85 F 78.2 00110 1
00107 Wendy 12-SEP-88 F 68.2 00110 1
00109 Michael 12-SEP-90 M 58.2 00110 1
00125 Angela 20-NOV-90 F 56.4 00120 2
00105 Robert 15-JAN-86 M 66.2 00150 3
00136 Aban 15-JAN-90 M 55.3 00200 4
00187 Eadger 07-APR-86 M 76.5 00250 5
14 rows selected.
WORKSON:
SQL> SELECT * FROM WORKSON;
E# P# HOURS
----- ------- -----
00110 1001 10
00101 1001 20
00150 1002 10
00105 1002 10
00105 1003 20
00105 1004 20
00250 1004 15
00187 1004 25
00105 1005 15
DEPARTMENT:
SQL> SELECT * FROM DEPARTMENT;
D# DNAME MANAG MSDATE
-- ------------------ ------ ------------
1 SALES 00110 02-JAN-12
2 ACCOUNTING 00120 30-OCT-10
3 GAMES 00150 01-MAR-08
4 HUMAN RESOURCES 00200 02-JAN-13
5 SPORTS 00250 10-MAY-10
PROJECT:
SQL> SELECT * FROM PROJECT;
P# PTITLE SPONSOR D# BUDGET
------ --- -------------- ---------------------- --- -------
1001 Computation Microsoft 1 25000
1002 Study methods Education committee 3 15000
1003 Racing car Cloud Pty Ltd 3 225000
1004 Football Football club 5 35000
1005 Swimming Education committee 5 125000
Any help would be greatly appreciated. Thanks in advance!
You first find the sum of hours of each employee and then join the same with your main table. Inline view can be used for the same.
SELECT EMPLOYEE.E#, EMPLOYEE.NAME, NVL(WORKSON_AGGR.TOTAL_HOURS,0)
FROM EMPLOYEE
LEFT JOIN (SELECT E#, SUM(HOURS) as TOTAL_HOURS
FROM WORKSON
GROUP BY E# ) WORKSON_AGGR
ON (WORKSON_AGGR.E# = EMPLOYEE.E#)
Now, you can join your department table too easily.
SELECT
E.E#,
E.NAME,
NVL(WORKSON_AGGR.TOTAL_HOURS,0),
D.DNAME
FROM EMPLOYEE E
LEFT JOIN (SELECT E#, SUM(HOURS) as TOTAL_HOURS
FROM WORKSON
GROUP BY E# ) WORKSON_AGGR
ON (WORKSON_AGGR.E# = E.E#)
JOIN DEPARTMENT D ON (D.D# = E.D#)

get extra rows for each group where date doesn't exist

I've been playing with this for days, and can't seem to come up with something. I have this query:
select
v.emp_name as Name
,MONTH(v.YearMonth) as m
,v.SalesTotal as Amount
from SalesTotals
Which gives me these results:
Name m Amount
Smith 1 123.50
Smith 2 40.21
Smith 3 444.21
Smith 4 23.21
Jones 1 121.00
Jones 2 499.00
Jones 3 23.23
Jones 4 41.82
etc....
What I need to do is use a JOIN or something, so that I get a NULL value for each month (1-12), for each name:
Name m Amount
Smith 1 123.50
Smith 2 40.21
Smith 3 444.21
Smith 4 23.21
Smith 5 NULL
Smith 6 NULL
Smith ... NULL
Smith 12 NULL
Jones 1 121.00
Jones 2 499.00
Jones 3 23.23
Jones 4 41.82
Jones 5 NULL
Jones ... NULL
Jones 12 NULL
etc....
I have a "Numbers" table, and have tried doing:
select
v.emp_name as Name
,MONTH(v.YearMonth) as m
,v.SalesTotal as Amount
from SalesTotals
FULL JOIN Number n on n.Number = MONTH(v.YearMonth) and n in(1,2,3,4,5,6,7,8,9,10,11,12)
But that only gives me 6 additional NULL rows, where what I want is actually 6 NULL rows for each group of names. I've tried using Group By, but not sure how to use it in a JOIN statement like that, and not even sure if that's the correct route to take.
Any advice or direction is much appreciated!
Here's one way to do it:
select
s.emp_name as Name
,s.Number as m
,st.salestotal as Amount
from (
select distinct emp_name, number
from salestotals, numbers
where number between 1 and 12) s left join salestotals st on
s.emp_name = st.emp_name and s.number = month(st.yearmonth)
Condensed SQL Fiddle
You could do:
SELECT EN.emp_name Name,
N.Number M,
ST.SalesTotal Amount
FROM ( SELECT Number
FROM NumberTable
WHERE Number BETWEEN 1 AND 12) N
CROSS JOIN (SELECT DISTINCT emp_name
FROM SalesTotals) EN
LEFT JOIN SalesTotals ST
ON N.Number = MONTH(ST.YearMonth)
AND EN.emp_name = ST.emp_name

How does select query works?

I having trouble with this query
it is executing quit well but I cannot make out
how is this select statement working.
Any help or explanation on this problem will be appreciated ..
thank you
these are my tables and query
here am looking for the employee who lives in same city as the the company for which they work
Table:-emp
eid name street city
----------- ---------------- ------------- ------------
1 yeman asd vasai
2 aksh adssd mumbai
3 chintan ghfgh mumbai
4 samual ghfdgh bandra
5 ddlj fghfgh andheri
6 jack fghnfg Bandra
7 bridge gfhfgh vasai
8 rahim ghfgh mumbai
9 chirag fghfghfg bandra
10 mistry hhhty bandra
11 ravi tytey andheri
Table:- company
cid companyname city
----------- ------------------- ------------
1 Vasai Industries vasai
2 Mumbai Pharmacy mumbai
3 bandra loft bandra
4 andheri tactics andheri
Table:= works
eid cid salary
----------- ----------- -----------
1 1 200
2 3 4831
3 4 4457
4 2 20001
5 1 32221
6 2 224
7 3 784
8 1 336
9 3 2489
10 2 4789
11 1 22541
Query
select * from emp
where eid
IN (select eid from works
where cid=(select cid from company
where city=emp.city))
why not use this query with joins and its easy to understand then a bunch of subqueries.
select * from emp
inner join works on works.eid = emp.eid
inner join company on company.city=emp.city
Explanation:
1.select cid from company where city=emp.city
Here you are getting city id regarding cities which are same in emp and company
2.
select eid from works
where cid=(select cid from company
where city=emp.city)
Here you getting collection of id's from works table which cid is same in emp and company
3.
select * from emp
where eid
IN (select eid from works
where cid=(select cid from company
where city=emp.city))
here you are getting all records based on emp id's whose cities are same in emp and city

Limiting records of combinations from 2 columns

looking for some help limiting the results while querying combinations between 2 columns. Here's an example of the kind of table I am working with..
id name group state
1 Bob A NY
2 Jim A NY
3 Dan A NY
4 Mike A FL
5 Tim B NY
6 Sam B FL
7 Brad B FL
8 Glen B FL
9 Ben C FL
I am trying to display all records of all combinations of "group" and "state", but limiting to displaying only up to 2 records for each combination. The result should look like the following..
id name group state
1 Bob A NY
2 Jim A NY
4 Mike A FL
5 Tim B NY
6 Sam B FL
7 Brad B FL
9 Ben C FL
Thanks for the help.
Assuming you always want the two rows for each group and state combination with the lowest id
SELECT *
FROM (SELECT a.*,
row_number() over (partition by group, state
order by id asc) rnk
FROM your_table a)
WHERE rnk <= 2
Of course, since group is a reserved word, I assume your column is actually named something else... You'd need to adjust my query to use the correct column name.