Passing values into CASE statement - database

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

Related

How to fix SSRS does NOT count NULL as value?

I'm creating a report using SSRS, and I have a bunch of departments and I need to count the total of their running statuses. This is the result from my table
Please note, the UNKNOWN department shows NULL inside the table. i hard coded to 'UNKNOWN' --ISNULL(department,'UNKNOWN')
And i have tested the table has NULL record and I can count those NULL record COUNT(*)
However, it seems like SSRS does not count NULL values.
the SSRS expression i had its =COUNT(Fields!ID.Value)
I need UNKNOWN rows count just as other department
How do I fix this?
I think your problem comes from how the query was written. This is a guess (you didn't provide the query) but I expect you did something like this:
/* Start Demo Data */
DECLARE #Departments TABLE (DepartmentID INT IDENTITY, Name NVARCHAR(50));
INSERT INTO #Departments (Name) VALUES
('Architect'),('Business Intelligence Analyst'),('Data Analyst'),
('Database'),('Information Technology'),('Technical Analyst');
DECLARE #Tickets TABLE (TicketID INT IDENTITY, CreateDateUTC DATETIME DEFAULT GETUTCDATE(), DepartmentID INT, Status NVARCHAR(50));
INSERT INTO #Tickets (DepartmentID, Status) VALUES
(1, 'Completed'),
(2, 'Completed'),(2, 'Completed'),
(3, 'Completed'),(3, 'Completed'),(3, 'Completed'),(3, 'Completed'),(3, 'Completed'),
(3, 'Failure'),(3, 'Failure'),(3, 'Running'),(3, 'Running'),(3, 'Failure'),
(4, 'Completed'),
(5, 'Completed'),(5, 'Completed'),(5, 'Failure'),(5, 'Running'),(5, 'Completed'),
(6, 'Completed'),
(7, 'Failure'),(7, 'Completed');
/* End Demo Data */
SELECT COALESCE(d.Name,'Unknown') AS Department,
COUNT(CASE WHEN t.Status = 'Completed' THEN 1 END) AS Completed,
COUNT(CASE WHEN t.Status = 'Failure' THEN 1 END ) AS Failure,
COUNT(CASE WHEN t.Status = 'Running' THEN 1 END ) AS Running,
COUNT(t.Status) AS Total
FROM #Departments d
INNER JOIN #Tickets t
ON t.DepartmentID = d.DepartmentID
GROUP BY d.Name
ORDER BY Department
Department Completed Failure Running Total
-----------------------------------------------------------------
Architect 1 0 0 1
Business Intelligence Analyst 2 0 0 2
Data Analyst 5 3 2 10
Database 1 0 0 1
Information Technology 3 1 1 5
Technical Analyst 1 0 0 1
This will find all the tickets with a matching department ID in the tickets table, but it will not return any tickets which have a non-matching value in the departmentID column, a NULL for example.
If you change your approach to something like:
SELECT COALESCE(d.Name,'Unknown') AS Department,
COUNT(CASE WHEN t.Status = 'Completed' THEN 1 END) AS Completed,
COUNT(CASE WHEN t.Status = 'Failure' THEN 1 END ) AS Failure,
COUNT(CASE WHEN t.Status = 'Running' THEN 1 END ) AS Running,
COUNT(t.Status) AS Total
FROM #Tickets t
LEFT OUTER JOIN #Departments d
ON t.DepartmentID = d.DepartmentID
GROUP BY d.Name
ORDER BY Department
You're now asking for all the tickets, and joining that to the departments with a LEFT OUTER JOIN which allows non-matching rows from Tickets to be returned as well. When there is a non-matching (including NULL) value in the departmentID column, it's still part of the result set.
Department Completed Failure Running Total
-----------------------------------------------------------------
Architect 1 0 0 1
Business Intelligence Analyst 2 0 0 2
Data Analyst 5 3 2 10
Database 1 0 0 1
Information Technology 3 1 1 5
Technical Analyst 1 0 0 1
Unknown 1 1 0 2

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

How to subtract two values from the same column SQL

I am building a procedure that when given a customerID it will subtract an account's type 2 (Credit card) balance from an account type 1 (Savings) balance, if there is an savings account then it subtracts the credit card balance.
(ex savings balance - credit card balance = total balance)
My table is set up like such
ID Number Balance AccountType CustomerID
-----------------------------------------------------------
1 2434789 451.23 1 1
2 2435656 1425.12 1 2
3 2434789 12.56 2 1
4 4831567 45894.23 2 2
5 8994785 500.00 2 3
6 4582165 243.10 2 4
7 7581462 1567842.21 1 3
8 2648956 1058.63 2 5
9 4582165 4865.12 1 4
10 4186545 481.56 2 6
I have tried looking this up to get some guidance but everything I have found hasn't quite helped me. If someone can explain or show me what I need to do that would be great, this is the only part of my assignment I am stuck on.
You could group by CustomerId and get the sum of saving and credit balances
select
c.CustomerId,
SUM(CASE WHEN AccountType = 1 THEN Balance ELSE 0 END) Saving,
SUM(CASE WHEN AccountType = 2 THEN Balance ELSE 0 END) Credit,
from
Customer c
group by
c.CustomerId
And then you can easily get the total with below query:
Select
CustomerId,
Saving - Credit
from
(
select
c.CustomerId,
SUM(CASE WHEN AccountType = 1 THEN Balance ELSE 0 END) Saving,
SUM(CASE WHEN AccountType = 2 THEN Balance ELSE 0 END) Credit,
from Customer c
group by c.CustomerId
) cust
You join the table to itself, where each side of the join only includes the appropriate account type records:
SELECT coalesce(s.CustomerID, cc.CustomerID) CustomerID
,coalesce(s.Number, cc.Number) Number
coalesce(s.Balance,0) - coalesce(cc.Balance,0) Balance
FROM (SELECT * FROM [accounts] WHERE AccountType = 2) s
FULL JOIN (SELECT * FROM [accounts] WHERE AccountType = 1) cc on cc.customerID = s.customerID

Distinct counts per year

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;

Count from a Count based on a condition in SQL server

I have 4 tables in my database.
Students (Idno, Name, CourseId)
Sample data:
Idno Name CourseId
------------------------
-101123456 Vijay 101
-101123457 John 102
-101123458 Sam 101
-101123459 Arvind 102
-101123460 Smith 101
Courses (CourseId, CourseNo, CourseName, StreamId)
Sample data:
CourseId CourseNo CourseName StreamId
------------------------------------------
-101 53245 C 1
-102 53245 C++ 2
Streams (StreamId, StreamName)
Sample data:
StreamId StreamName
---------------------------
-1 Engineering
-2 Medical
Booking (BId, Idno, BStatus)
Sample data:
Bid Idno BStatus
--------------------------------
-1110 101123456 Confirmed
-1111 101123456 Confirmed
-1112 101123457 Confirmed
-1113 101123458 Confirmed
-1114 101123459 Confirmed
-1115 101123460 Confirmed
-1116 101123456 Confirmed
-1117 101123457 Confirmed
-1118 101123458 Confirmed
-1119 101123459 Confirmed
-1119 101123460 Cancelled
I have a problem generating the following output
SNo Stream BookedOnce BookedTwice NonBooked
1 Engineering 2 3 0
2 Medical 3 1 1
Thanks
I think this requires a two step process. First, calculate the number of bookings by each student for a stream. Then per stream, count the number of students that have one, two or zero bookings.
Here's an example, with the first step in the inner query:
select StreamId
, StreamName
, sum(case when Bookings = 1 then 1 else 0 end) as BookedOnce
, sum(case when Bookings = 2 then 1 else 0 end) as BookedTwice
, sum(case when Bookings = 0 then 1 else 0 end) as NoneBooked
from (
select str.StreamId
, str.StreamName
, s.Idno
, count(b.BId) as Bookings
from Students s
left join
Booking b
on b.Idno = s.Idno
left join
Courses c
on c.CourseId = s.CourseId
left join
Streams str
on str.StreamId = c.StreamId
group by
str.StreamId
, str.StreamName
, s.Idno
) BookingsPerStudentPerStream
group by
StreamId
, StreamName

Resources