SUM() with entries from 2 table - sql-server

Select p.pnum,
SUM(CASE WHEN P.NegativeScreen = 'Type99' THEN 1 ELSE 0 END) TotalDetected,
SUM(IIF(P.IsPositive = 1, 1,0)) TotalP,
SUM(CASE WHEN (P.MethId NOT IN (4, 8, 10, 25) THEN 1 ELSE 0 END) Total,
SUM(CASE WHEN (P.MethID IN (34,64) ) THEN 1 ELSE 0 END) TotalVal1,
SUM(CASE WHEN (P.MethID IN (16,64) ) THEN 1 ELSE 0 END) TotalVal2,
SUM(CASE WHEN (P.MethID IN (2,4,6,11,13,14,15,18,21,22,24,28,30,31) OR (P.MethID
= 1 AND P.TotalCount IS NOT NULL)) THEN 1 ELSE 0 END) TotalMethOther,
FROM tbl_plt p
GROUP BY P.PNum
Notice that the above query has all the fields from the tbl_plt table and SUM() is done on the fields.
Notice where I have MethID mentioned above. I need to check if those MethID exist in the tbl_plt table and if they exist in another table called TblOther. If so, tally it up accordingly.
Here is the fields in TblOther Table. Note that in TblOther table, we can have multiple PNums but the MethID will be different. Also note that for not all pNums will have entries in the TblOther table.
ID PNum MethID
1 232 32
2 232 64
3 232 10
4 104 14
5 104 54
6 22 4
7 4 13
I tried with LEFT JOIN with TblOther table but things gets messy as with the left join, it also tallies up incorrectly for places like:
SUM(CASE WHEN P.NegativeScreen = 'Type99' THEN 1 ELSE 0 END) TotalDetected,
SUM(IIF(P.IsPositive = 1, 1,0)) TotalP,
As an example for where I have:
SUM(CASE WHEN (P.MethID IN (34,64) ) THEN 1 ELSE 0 END)
it needs get the count of how many MethID exist in both the tblOther and tbl_plt for where MethID is 34 or 64 for the associated PNum.
It needs to do similarly for other places where MethID is mentioned.

I don't know enough about TblOther or it's join, but I suspect you might need to do the same group by (i.e., PNum) on it before joining on PNum. Then the left join will match either 0 or 1 records. Be sure to account for the null if there is no match.

You could start by getting the list of distinct PNum and MethIDs to use and then do your summing based on that list:
;WITH entries as (
SELECT DISTINCT PNum, MethID
FROM tblOther)
SELECT *
FROM entries
INNER JOIN tbl_plt
ON entries.PNum = tbl_plt.PNum
AND entries.MethID = tbl_plt.MethID
GROUP BY entries.PNum

Related

SQL - Summing aggregate sub query

This is the code I have
select distinct sli.order_no,
sli.pkg_no,
case when line.primary_ind = 'Y' then sum(paid_amt) else 0 end as paid_amt,
line.pkg_li_no,
sum(case when sli.perf_no = 0 then 1 else 0 end) as num_seats_pur,
sli.status
from t_sub_line sli
left outer join t_line line on sli.li_seq_no = line.li_seq_no
where sli.order_no in (1,2)
group by
sli.order_no,
sli.pkg_no,
line.primary_ind,
line.pkg_li_no,
sli.status
having line.primary_ind = 'Y'
This code produces this output
order_no pkg_no paid_amt pkg_li_no num_seats_pur status
1 322 124.00 967 2 7
1 322 -124.00 992 2 4
2 854 253.00 952 1 7
2 854 -253.00 996 1 4
what I really need for the data to return is the following. I need the sum of paid_amt field.
order_no pkg_no paid_amt pkg_li_no num_seats_pur status
1 322 0 967 2 7
2 854 0 996 1 4
even if i change status to be max(status) so its not grouping on it. I don't have sum_paid amt.
when i try this code:
sum(case when line.primary_ind = 'Y' then sum(paid_amt) else 0 end) as paid_amt,
I get the following error message
Cannot perform an aggregate function on an expression containing an aggregate or a subquery.
A couple things you need to do.
Comment out pkg_li_no from the select and group by
Change the having statement to be included in the where statement
Remove the case from paid_amt since it is not necessary
select distinct sli.order_no,
sli.pkg_no,
sum(paid_amt)as paid_amt,
-- line.pkg_li_no,
sum(case when sli.perf_no = 0 then 1 else 0 end) as num_seats_pur,
sli.status
from t_sub_line sli
left join t_line line on sli.li_seq_no = line.li_seq_no
where sli.order_no in (1,2)
and line.primary_ind = 'Y'
group by
sli.order_no,
sli.pkg_no,
line.primary_ind,
-- line.pkg_li_no,
sli.status
Other notes:
I am not sure you want to select or group by the pkg_no or status, but you know more what outcome are looking for. If they are different values, there will be different records.
I'm not sure what you're trying to accomplish, but it seems that you overthinking the query. Try to simplifying it.
FYI HAVING happens after the grouping, WHERE happens before the grouping, you don't even need the CASE
select distinct sli.order_no,
sli.pkg_no,
sum(paid_amt) as paid_amt,
sum(case when sli.perf_no = 0 then 1 else 0 end) as num_seats_pur,
sli.status
from t_sub_line sli
left outer join t_line line on sli.li_seq_no = line.li_seq_no
where sli.order_no in (1,2)
and line.primary_ind = 'Y'
group by
sli.order_no,
sli.pkg_no,
sli.status

SUM values when conditions met

I have the following SQL Server table with the following data:
PRICE(decimal 9,2) PRICETYPE(int) EVENTDETAILID (int)
PRICE PRICETYPE EVENTDETAILID
------------------------------------------------
99 1 1
99 1 1
99 1 1
15 0 1
15 0 1
50 1 2
50 1 2
I want to SUM the PRICE of the results with the following conditions:
for each EVENTDETAILID, SUM every line with a pricetype is 0 and for every line per EVENTDETAILID pricetype is 1, then add it only 1 time.
For the above example the required output would be:
99 + 15 + 15 for eventDetailId = 1
50 for eventDetailsId = 2
I've tried the following but doesn't work as expected as I'm not able to add PRICE only once if PRICETYPE is 1:
SELECT
SUM(PRICE)
FROM
ReservationDetails
GROUP BY
eventDetail_id
You may phrase this as an aggregation (GROUP BY) query over the event detail ID. The sum can be broken into a conditional sum when the detail ID is 0, combined with the maximum price when the detail ID is 1. Since you told us that the price is always the same when PRICETYPE=1, therefore we can choose any single value.
SELECT
EVENTDETAILID,
SUM(CASE WHEN PRICETYPE = 0 THEN PRICE ELSE 0 END) +
MAX(CASE WHEN PRICETYPE = 1 THEN PRICE ELSE 0 END) AS total
FROM yourTable
GROUP BY
EVENTDETAILID
ORDER BY
EVENTDETAILID;
Demo

I need to write proc which give me report of all my Student, the Male and Female but per different Country?

I have data for my Student in my lookupdata table (Enrolled, Droped Out, Canclled, all with ldTypeID = 129). The rest of my data is stored in vStudent. I need to write proc which will give me a report of all my Student, the Male and Female but per different Country. Where did I go wrong with my code?
Student Status Total Number Total # Males Total # Females
Enrolled
Dropped Out
Cancelled
Graduated
CREATE PROCEDURE [dbo].[pr_ReportPerCountry]
#CountryID int
AS
DELETE FROM ReportData WHERE rdTypeID = 2
INSERT INTO ReportData
(
rdSortBy,
rdTypeID,
rdName1,
rdValue1,
rdValue2,
rdValue3,
)
Select
0 AS SoryBy,
2 AS rdTypeID,
finalStudentStatus,
sum (case when peFinalStatusID in (303) then 1 else 0 end) as TotalEnrolled,
sum(case when (peFinalStatusID in (303) and peSexID=7) then 1 else 0 end) as MaleEnrolled,
sum(case when (peFinalStatusID in (303) and peSexID=8) then 1 else 0 end) as FemaleEnrolled
from vStudentPerson
left join (SELECT ldLookupDataID,ldValue FROM LookupData
WHERE ldTypeID = 129
group by ldLookupDataID,ldValue
) sta on peFinalStatusID=sta.ldLookupDataID
WHERE peFinalStatusID in (297,298,299,303) and peCountryofResidencyID = 0 or peCountryofResidencyID=#CountryID
I find solution, thanks anyway.
INSERT INTO ReportData
(
rdSortBy,
rdTypeID,
rdName1,
rdValue1,
rdValue2,
rdValue3
)
Select
0 AS SoryBy,
1 AS rdTypeID,
academicYear,
count (pePersonID) as TotalAwarded,
sum (case when peSexID = 7 then 1 else 0 end ) as TotalAwardedMale,
sum (case when peSexID = 8 then 1 else 0 end ) as TotalAwardedFemale
from vStudentPerson
left join (SELECT * FROM vStudentPersonScholarship) sch on pePersonID=sch.psPersonID
where (#CountryID = -1 or peCountryofResidencyID = #CountryID) and psScholarahipRenewalsTypeID=281
group by sch.academicYear

COUNT and COUNT DISTINCT for different groups

For a SQL Server based report,
Table:
CID Date ID Service Days
1 3/7/2016 1 Individual 3
2 4/5/2016 2 Individual 4
3 5/24/2016 1 Individual 3
4 4/4/2016 4 Group 2
5 4/4/2016 4 Group 2
6 2/18/2016 4 Group 2
7 5/5/2016 5 Group 1
8 5/5/2016 5 Group 1
I used this code:
SELECT
ID,
Service,
COUNT(WHEN Days = 4 THEN 1 END) AS '4Days',
COUNT(WHEN Days = 3 THEN 1 END) AS '3Days',
COUNT(WHEN Days = 2 THEN 1 END) AS '2Days',
COUNT(WHEN Days = 1 THEN 1 END) AS '1Day'
FROM Table T1
GROUP BY
ID,
Service
which gives me this Output:
ID Service 4Days 3Days 2Days 1Day
1 Individual 0 2 0 0
2 Individual 1 0 0 0
4 Group 0 0 3 0
5 Group 0 0 0 2
What I want to do is not count the Group services as separate services for separate individuals, but just as one service per group. A Count Distinct used with the Date or ID could help me do that but I don't know how to make that play with the Individual services where I just wanna count them individually and not using DISTINCT. So the desired output is:
ID Service 4Days 3Days 2Days 1Day
1 Individual 0 2 0 0
2 Individual 1 0 0 0
4 Group 0 0 2 0
5 Group 0 0 0 1
I'll edit the post in case I oversimplified the problem since this is dummy data.
Looks like you could use distinct this way if you wanted:
count(distinct
case when Days = 1 then case when Service = 'Group' then 1 else "Date" end end
) as [1Day]
Depending on your indexing it's possible that introducing another column in the query would change the query plan. I suspect that probably isn't the case though.
If I am not wrong for '2Days' column service type 'Group' count should be '2' if our grouping based on 'Date' column, if so then try this:
SELECT
ID,
Service,
CASE WHEN MAX(t.days) = 4 THEN MAX(t.date) ELSE 0 END AS '4Days',
CASE WHEN MAX(t.days) = 3 THEN MAX(t.date) ELSE 0 END AS '3Days',
CASE WHEN MAX(t.days) = 2 THEN MAX(t.date) ELSE 0 END AS '2Days',
CASE WHEN MAX(t.days) = 1 THEN MAX(t.date) ELSE 0 END AS '1Day'
FROM table T1
OUTER APPLY (SELECT days,
COUNT(DISTINCT(date)) date
FROM Table WHERE days = t1.days GROUP BY days) t
GROUP BY id, service
ORDER BY ID
Based on your last edit, this is the most straight forward way I could think of to handle the query:
with cte as (
select id, service, days
from table t1
where service = 'Individual'
union all
select id, service, days
from table t1
where service = 'Group'
group by id, service, days, date
)
select id,
service,
count(case when days = 4 then 'X' end) as [4Days],
count(case when days = 3 then 'X' end) as [3Days],
count(case when days = 2 then 'X' end) as [2Days],
count(case when days = 1 then 'X' end) as [1Day]
from cte
group by id, service

Passing values into CASE statement

and thank you all in advance for your help.
I'm trying to take the results from two separate queries and include them in a third query that has a CASE statement. I've had some success but I'm not able to present the results of the third query in the proper order. The purpose of this is to show the employee count for each department under the different managers. So far I can only load separately the manager names and their departments and employee department count totals by department. What I can't figure out is how to get the manager names in and the employee department count in for each manager row. Below are the two source queries I've used so far and the query with the CASE statement. I've also looked at UNPIVOT function with no success yet.
a) This simple query lists each primary manager name. There are also sub managers that will be returned using a hierarchy query later.
select name from employees "Boss" where employeeid in
(‘1’,'5','25','84','85');
b) This query returns the department id count for each main manager (‘1’,'5','25','84','85') as well as all sub-managers.
select departmentid, count(departmentid) COUNT from employees
where departmentid = departmentid and level <= 3
connect by prior employeeid = bossid
start with employeeid = 5
group by departmentid
order by departmentid;
c) Here’s a CASE statement that outputs exactly as desired. The problem here is the select statement currently outputs only the manager names and the manager departments into the columns. What I need to do is output both the manager names and the manager's employee department counts into the individual manager row columns. I've tried to do a separate select of the manager names to get the ‘Boss’ column and another select to include the department counts. But that got messy. Also passing the counts in a second statement would create an additional unwanted column.
select e.name "Boss",
COUNT(CASE WHEN d.departmentid = '1' THEN 1 END) AS "Finance",
COUNT(CASE WHEN d.departmentid = '2' THEN 1 END) AS "HR",
COUNT(CASE WHEN d.departmentid = '3' THEN 1 END) AS "IT",
COUNT(CASE WHEN d.departmentid = '4' THEN 1 END) AS "Marketing",
COUNT(CASE WHEN d.departmentid = '5' THEN 1 END) AS "Sales"
from employees e, departments d
where e.employeeid in (select distinct e.bossid from employees e)
and e.departmentid = d.departmentid (+)
group by e.name
order by e.name;
Boss Finance HR IT Marketing Sales
-------------------- ---------- ---------- ---------- ---------- ----------
Baxter Carney 0 0 0 0 1
Blythe Pierce 0 0 0 0 1
Here's an altered CASE query that loads the employee department counts but unfortunately it loads by department and not by individual manager. That is the problem I'm stuck on right now. How to pass the counts to the right manager and into the right column.
select departmentid "DEPTNO",
COUNT(CASE WHEN departmentid = '1' THEN 1 END) AS "Finance",
COUNT(CASE WHEN departmentid = '2' THEN 1 END) AS "HR",
COUNT(CASE WHEN departmentid = '3' THEN 1 END) AS "IT",
COUNT(CASE WHEN departmentid = '4' THEN 1 END) AS "Marketing",
COUNT(CASE WHEN departmentid = '5' THEN 1 END) AS "Sales"
from employees
where departmentid = departmentid and level <= 3
connect by prior employeeid = bossid
start with employeeid = 5
group by departmentid
order by departmentid
/
DEPTNO Finance HR IT Marketing Sales
3 0 0 1 0 0
5 0 0 0 0 21
And here's for all managers. You can see that it just keeps increasing the individual department count.
DEPTNO Finance HR IT Marketing Sales
1 4 0 0 0 0
2 0 23 0 0 0
3 0 0 20 0 0
4 0 0 0 1 0
5 0 0 0 0 28

Resources