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
Related
I have a need to concatenate name information from two tables in a specific order. So far, all I have is the SQL to retrieve the data. I need help with the SQL to output a name string in the correct order.
example data:
TBL_TITLE_ORDER
ORDER_ID
ORDER_SEQUENCE
TITLE_ID
FIRSTNAME_ID
20
1
30
20
2
456
20
3
33
21
1
31
21
2
32
TBL_TITLE
TITLE_ID
TITLE_NAME
30
Mr
31
Mrs
32
Jones
33
Smith
TBL_FIRSTNAME
FIRSTNAME_ID
NAME
456
John
SELECT TBL_TITLE.TITLE_NAME, TBL_FIRSTNAME.NAME
FROM (TBL_TITLE_ORDER LEFT JOIN TBL_TITLE ON TBL_TITLE_ORDER.TITLE_ID = TBL_TITLE.TITLE_ID) LEFT JOIN TBL_FIRSTNAME ON TBL_TITLE_ORDER.FIRSTNAME_ID = TBL_FIRSTNAME.FIRSTNAME_ID
WHERE (TBL_TITLE_ORDER.ORDER_ID) = 20
ORDER BY TBL_TITLE_ORDER.ORDER_SEQUENCE;
The output I need is a complete name string in the proper order sequence. There may or may not be a record in the TBL_FIRSTNAME table.
What I have so far:
TITLE_NAME
NAME
Mr
John
Smith
Required output:
Mr John Smith
Mrs Jones
I've been tasked with returning only rows with unique IDs but returning a row for every ID in SQL. How would I go about this?
Logic:
For primary row, select where JOB_INDICATOR = āPā. If there are multiple rows, then use the record where PRIM_ROLE_IND = āYā. If there are still multiple then select the lowest numbered EMPL_RCD starting at 0.
Example starting point:
id
name
job
job_indicator
prim_role_ind
empl_rcd
1001
John Doe
Director
P
N
0
1001
John Doe
Professor
P
Y
1
1001
John Doe
Coach
N
N
2
1002
Bob Jones
Head Janitor
P
Y
0
1002
Bob Jones
Associate Janitor
P
Y
1
1003
Susan Smith
Groundskeeper
P
N
0
1003
Susan Smith
Professor
P
N
1
Desired return:
id
name
job
job_indicator
prim_role_ind
empl_rcd
1001
John Doe
Professor
P
Y
1
1002
Bob Jones
Head Janitor
P
Y
0
1003
Susan Smith
Groundskeeper
P
N
0
So far, I have the below, but a new requirement was added to do conditional components.
SELECT *
FROM EMPLOYEE
WHERE JOB_INDICATOR = 'P'
You can use window function ROW_NUMBER() to accomplish this:
SELECT *
FROM
(
SELECT EMPLOYEE.*, ROW_NUMBER() OVER (PARTITION BY id ORDER BY
prim_role_ind DESC, empl_rcd ASC) as rn
FROM EMPLOYEE
WHERE JOB_INDICATOR = 'P'
) dt
WHERE rn = 1
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.
I have a table with IDs and primary information. I also have two delta tables keyed on ID and date of change. I need to build a view that merges these three tables together indicating all changes over time.
Main Table:
ID Name
-- ------------------
1 Bob Jones
2 Dave Smith
First Attribute Table:
ID Date Attr1
-- ---------- -----
1 01/01/2013 25
1 02/15/2013 33
1 02/17/2013 47
1 03/02/2013 58
2 02/01/2013 1
...
Second Attribute Table
ID Date Attr2
-- ---------- -----
1 01/01/2013 ABC
1 01/05/2013 DEF
1 01/15/2013 RST
1 02/10/2013 XYZ
1 02/15/2013 Foo
1 03/05/2013 Blah
2 02/01/2013 Two
...
Based on that data, for Bob Jones, I need the view to return the following:
ID Name Date Attr1 Attr2
-- ----------- ---------- ----- -----
1 Bob Jones 01/01/2013 25 ABC
1 Bob Jones 01/05/2013 25 DEF
1 Bob Jones 01/15/2013 25 RST
1 Bob Jones 02/10/2013 25 XYZ
1 Bob Jones 02/15/2013 33 Foo
1 Bob Jones 02/17/2013 47 Foo
1 Bob Jones 03/02/2013 58 Foo
1 Bob Jones 03/05/2013 58 Blah
I tried outer joining the attribute tables to get all change values ordered by date and then used an outer join on the entire query with itself to get "prior" records:
with qry as (
select
rownum = ROW_NUMBER() OVER (ORDER BY m.ID, a.DATE),
m.ID,
m.Name,
a.DATE,
a.Attr1,
a.Attr2
from Main m
inner join (
select
COALESCE(a1.ID, a2.ID) as ID,
COALESCE(a1.LOAD_DATE, a2.LOAD_DATE) as LOAD_DATE,
a1.Attr1,
a2.Attr2
from Attributes1 a1
full outer join Attributes2 a2
on (a1.ID = a2.ID and a1.DATE = a2.DATE)
) a on (a.ID = m.ID)
)
select
COALESCE(qry.ID, prev.ID) as ID,
COALESCE(qry.Name, prev.Name) as Name,
COALESCE(qry.DATE, prev.DATE) as DATE,
COALESCE(qry.Attr1, prev.Attr1) as Attr1,
COALESCE(qry.Attr2, prev.Attr2) as Attr2,
from qry
left join qry prev
on (prev.rownum = qry.rownum - 1)
order by ID, DATE
However, that doesn't work when one attribute table changes quicker than the other because the attributes that didn't change are null in the results of the attribute table join and if two nulls show up back-to-back, the coalesce will return a null when I need the last non-null value that was in that column.
Can this even be done in a view in SQL Server 2012?
I'm fairly new to SQL server (this is my second post on StackOverflow). I'm currently using SQL Server 2008 R2. I have a few tables that I've joined with the following query:
SELECT pt.first_name, pt.last_name, pt.provider_id,
pt.last_visit_date, pl.last_name
FROM dbo.pm_patient pt
INNER JOIN dbo.ProviderList pl
ON pt.provider_id = pl.provider_id
WHERE pt.last_visit_date >= '02/01/2012' AND pt.last_visit_date <= '02/01/2013'
ORDER BY provider_id
The result of the above query looks something like this:
first_name last_name provider_id last_visit_date last_name
Smith John 1 04/25/2012 Johnson
Doe Jane 1 02/25/2012 Johnson
Davies Ann 1 03/15/2012 Johnson
Dupree David 1 11/20/2012 Johnson
Jones Becky 1 04/21/2012 Smith
Diaz Mike 1 02/12/2012 Smith
Williams Allison 1 08/05/2012 Smith
Taylor Joe 1 10/01/2012 Smith
I would rather simply get the following result:
last_name NoOfPatients
Johnson 4
Smith 4
Could someone please help me?
Try :
SELECT pl.last_name, count(*) NoOfPatients
FROM dbo.pm_patient pt
INNER JOIN dbo.ProviderList pl
ON pt.provider_id = pl.provider_id
WHERE pt.last_visit_date >= '02/01/2012' AND pt.last_visit_date <= '02/01/2013'
GROUP BY pl.last_name
You need to read about how to use group in querys, basically what you need to do is count the number of patients and group by providers.
SELECT pt.last_name, COUNT(pt.*) NoOfPatients
FROM dbo.pm_patient pt
INNER JOIN dbo.ProviderList pl
ON pt.provider_id = pl.provider_id
WHERE pt.last_visit_date >= '02/01/2012' AND pt.last_visit_date <= '02/01/2013'
ORDER BY provider_id
GROUP BY pt.last_name