Grouping multiple counts with each row representing one ID - sql

I have a table that logs activity. It has an int activity column that indicates what type of activity it was and a corresponding admin_id that indicates which admin performed the action. Each row in the table represents one action, so for example, an administrator would cancel a user's account, and a row with that admin's id and activity=[int representing cancel] would be created. I need a way to a select a result which groups each admin's activity such that the row corresponding to the admin would have the # of each activity
The result would look like
admin_id | numActivated | numCanceled | numRenewed
1 1 1 2
2 1 3 0
With numActivated, numCanceled, and numRenewed all coming from the count for each activity.
This is what the original table would have looked like:
admin_id | activity ...
1 2
1 1
1 3
1 3
2 2
2 2
2 2
2 1
(activity 1: activate, 2: cancel, 3: renew)
Thanks

This should do what you're asking for:
select admin_id,
sum(case when activity = 1 then 1 else 0 end) as numActivated,
sum(case when activity = 2 then 1 else 0 end) as numCanceled,
sum(case when activity = 3 then 1 else 0 end) as numRenewed
from YourTable
group by admin_id

This should do it:
SELECT
T.admin_id,
sum(T.activate) AS numActivated,
sum(T.canceled) AS numCanceled,
sum(T.renew) AS numRenewed
FROM (
SELECT
admin_id,
CASE activity WHEN 1 THEN 1 ELSE 0 END AS activate,
CASE activity WHEN 2 THEN 1 ELSE 0 END AS canceled,
CASE activity WHEN 3 THEN 1 ELSE 0 END AS renew
FROM Table
) AS T
GROUP BY T.admin_id

Related

How to check the count of each values repeating in a row

I have two tables. Data in the first table is:
ID Username
1 Dan
2 Eli
3 Sean
4 John
Second Table Data:
user_id Status_id
1 2
1 3
4 1
3 2
2 3
1 1
3 3
3 3
3 3
. .
goes on goes on
These are my both tables.
I want to find the frequency of individual users doing 'status_id'
My expected result is:
username status_id(1) status_id(2) status_id(3)
Dan 1 1 1
Eli 0 0 1
Sean 0 1 2
John 1 0 0
My current code is:
SELECT b.username , COUNT(a.status_id)
FROM masterdb.auth_user b
left outer join masterdb.xmlform_joblist a
on a.user1_id = b.id
GROUP BY b.username, b.id, a.status_id
This gives me the separate count but in a single row without mentioning which status_id each column represents
This is called pivot and it works in two steps:
extracts the data for the specific field using a CASE statement
aggregates the data on users, to make every field value lie on the same record for each user
SELECT Username,
SUM(CASE WHEN status_id = 1 THEN 1 END) AS status_id_1,
SUM(CASE WHEN status_id = 2 THEN 1 END) AS status_id_2,
SUM(CASE WHEN status_id = 3 THEN 1 END) AS status_id_3
FROM t2
INNER JOIN t1
ON t2.user_id = t1._ID
GROUP BY Username
ORDER BY Username
Check the demo here.
Note: This solution assumes that there are 3 status_id values. If you need to generalize on the amount of status ids, you would require a dynamic query. In any case, it's better to avoid dynamic queries if you can.

TRIGGER to calculate the total leaves of each left type group by employee

I have 2 tables like this
EmployeeID
LeaveTypeID
1
1
2
2
1
2
1
2
Now I want a TRIGGER that calculate automatically total of type 1 and type 2 in below table
EmployeeID
Type1
Type2
1
1
2
2
0
1
No need for triggers. Just create a view that has the aggregation in it
CREATE VIEW vTotal
AS
SELECT
t.EmployeeID,
Type1 = COUNT(CASE WHEN t.LeaveTypeID = 1 THEN 1 END),
Type2 = COUNT(CASE WHEN t.LeaveTypeID = 2 THEN 1 END)
FROM dbo.YourTable t
GROUP BY
t.EmployeedID;

How to add column to an existing SQL Server table based on condition?

I want to add a column to an existing table based on the condition of 3 columns in the table like the example below.
I have 3 columns :
EXPIRED
pending
on_the_go
where each column had as value the ID number from another table of the corresponding value (expired value is 1)(pending value is 2)...
What I want is to add a column called status that combine all these 3 columns into 1
I tried to use CASE WHEN but that did not work as expected:
SELECT
EXPIRED, pending, on_the_go,
CASE EXPIRED
WHEN 1 THEN 1
END AS status_type,
CASE pending
WHEN 2 THEN 2
END AS status_type,
CASE on_the_go
WHEN 3 THEN 3
END AS status_type,
COUNT(*) AS number_of_exchange_activities
FROM
card
GROUP BY
EXPIRED, pending, on_the_go
EXPIRED
pending
on_the_go
status_type
status_type
status_type
number_of_exchange_activities
0
2
0
NULL
2
NULL
550
0
0
3
NULL
NULL
3
320
1
0
0
1
NULL
NULL
310
This is what I expected to get:
EXPIRED
pending
on_the_go
status_type
number_of_exchange_activities
0
2
0
2
550
0
0
3
3
320
1
0
0
1
310
You can use the long form of case that allows you to place full conditions in each when clause:
SELECT expired, pending, on_the_go,
CASE WHEN expired = 1 THEN 1
WHEN pending = 2 THEN 2
WHEN on_the_go = 3 THEN 3
END AS status_type,
COUNT(*) AS number_of_exchange_activities
FROM card
GROUP BY expired, pending, on_the_go
CASE
WHEN EXPIRED = 1 THEN 1
WHEN pending = 2 THEN 2
WHEN on_the_go = 3 THEN 3
ELSE 0
END As 'status_type'

SQL Server : how can I get difference between counts of total rows and those with only data

I have a table with data as shown below (the table is built every day with current date, but I left off that field for ease of reading).
This table keeps track of people and the doors they enter on a daily basis.
Table entrance_t:
id entrance entered
------------------------
1 a 0
1 b 0
1 c 0
1 d 0
2 a 1
2 b 0
2 c 0
2 d 0
3 a 0
3 b 1
3 c 1
3 d 1
My goal is to report on people and count entrances not used(grouping on people), but ONLY if they entered(entered=1).
So using the above table, I would like the results of query to be...
id count
----------
2 3
3 1
(id=2 did not use 3 of the entrances and id=3 did not use 1)
I tried queries(some with inner joins on two instances of same table) and I can get the entrances not used, but it's always for everybody. Like this...
id count
----------
1 4
2 3
3 1
How do I not display results id=1 since they did not enter at all?
Thank you,
You could use conditional aggregation:
SELECT id, count(CASE WHEN entered = 0 THEN 1 END) AS cnt
FROM entrance_t
GROUP BY id
HAVING count(CASE WHEN entered = 1 THEN 1 END) > 0;
DBFiddle Demo

SQL Count number of values given compound condition on row

I have a table as follows:
User ID Service
1 2
1 3
2 1
2 3
3 5
3 3
4 3
5 2
How could I construct a query where I would count all the user ids that have a service of 3 and at least one other service?
In the above table, the query I'm interested in would return 3 because user ids 1, 2 and 3 have service of 3 and at least one other service.
Thanks!
In MS SQL:
select count(*)
from UserService
where
ServiceId = 3 and
UserId in (select UserId from UserService where ServiceId != 3)
EDIT In response to comments:
select count(*) from (
select userId
from theTable
group by userId
having sum(case when service = 3 then 1 else 0 end) > 0
and sum(case when service <>3 then 1 else 0 end) > 0
) x