Distinct counts per year - sql-server

hello I am trying to count a person only once even if a person has two enrollments in the same year:
select DISTINCT Year, School,
count (case when [Graduate]= 1 AND [Dropout]= 0 THEN ID END) As 'passed',
count (case when [Graduate]= 0 AND [Dropout]= 1 THEN ID END) as 'dropped',
count (case when [Graduate]= 0 AND [Dropout]= 0 THEN ID END) as 'Continued'
from Table where ID = '10'
group by Year, School
my output is
Year school passed dropped continued
2012 School 0 0 1
2013 School 0 0 1
2014 School 0 0 2
continued is 2 for ID=1 because student enrolled twice. How do i get a distinct count in this case?

You are using DISTINCT wrong, it should be inside each COUNT:
SELECT [Year],
School,
COUNT(DISTINCT CASE WHEN [Graduate] = 1 AND [Dropout] = 0 THEN ID END) Passed,
COUNT(DISTINCT CASE WHEN [Graduate] = 0 AND [Dropout] = 1 THEN ID END) Dropped,
COUNT(DISTINCT CASE WHEN [Graduate] = 0 AND [Dropout] = 0 THEN ID END) Continued
FROM YourTable
WHERE ID = '10'
GROUP BY [Year],
School;

Related

Count the number columns using NOT NULL in a case statement

I need some help with my query...I am trying to get a count of names in each house, all the col#'s are names.
Query:
SELECT
House#,
COUNT(CASE WHEN col#1 IS NOT NULL THEN 1 ELSE 0 END) +
COUNT(CASE WHEN col#2 IS NOT NULL THEN 1 ELSE 0 END) +
COUNT(CASE WHEN col#3 IS NOT NULL THEN 1 ELSE 0 END) AS count
FROM
myDB
WHERE
House# IN (house#1, house#2, house#3)
GROUP BY
House#
Desired results:
house 1 - the count is 3
house 2 - the count is 2
house 3 - the count is 1
...with my current query the results for count would be just 3's
COUNT by design doesn't count NULL values.
SELECT House#,
COUNT(col1#) + COUNT(col2#) + COUNT(col3#) AS count
FROM myDB
WHERE House# IN (house#1,house#2,house#3)
GROUP BY House#;

How to flatten this multiple rows into one?

I have data like this: (table name: Activities)
ActivityId CreatedOn TypeId
1 2017-01-01 1
1 2017-01-02 1
1 2017-01-02 2
2 2017-01-01 3
Where Type is a lookup value: (table name: Types)
TypeId Name
1 Question
2 Answer
3 Comment
Basically it's an activity history table.
I want to turn the above tables into a grouped sum row for types, for each ActivityId, like this:
ActivityId QuestionCount AnswerCount CommentCount
1 2 1 0
2 0 0 1
I know the answer is probably pretty simple, but it's eluding me for some reason.
Any help? Thanks in advance.
A simple join and conditional aggregation should do the trick (I suspect you were over-thinking it)
Select ActivityID
,QuestionCount = sum(case when Name='Question' then 1 else 0 end)
,AnswerCount = sum(case when Name='Answer' then 1 else 0 end)
,CommentCount = sum(case when Name='Comment' then 1 else 0 end)
From Activities A
Join Types B on A.TypeId=B.TypeId
Group By ActivityId
Returns
ActivityID QuestionCount AnswerCount CommentCount
1 2 1 0
2 0 0 1
You could also do it without the Join... Just less readable
Select ActivityID
,QuestionCount = sum(case when TypeId=1 then 1 else 0 end)
,AnswerCount = sum(case when TypeId=2 then 1 else 0 end)
,CommentCount = sum(case when TypeId=3 then 1 else 0 end)
From #Activities A
Group By ActivityId
You could also try a PIVOT
Select ActivityID
,[1] as QuestionCount
,[2] as AnswerCount
,[3] as CommentCount
From (Select ActivityId,TypeID,1 as Cnt From #Activities) A
Pivot (count(Cnt) For TypeId in ([1],[2],[3]) ) p

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