Reputation: 13
I have used T-SQL for an awfully long time not to be able to do aggregation any better than I do, and this example will highlight that. I'm sure there are probably questions out there dealing with this but, not knowing any better about how to ask it, I also don't know any better how to search for it.
I have a view that aggregates some activity logging per team member Sample ActivityDetail ...
One of the things I need to do with this is get an aggregation (Activity Count by Member) for all Team Members for a given time period. I found it easy enough to get Per-Activity Totals in a dedicated row per Member/Activity using a concatenation hack found elsewhere on this site
SELECT DISTINCT
a.Member
, a.Activity
, COUNT(CONCAT(a.Member,a.Activity)) AS ActivityCount
FROM v_Activity a
WHERE a.Activity_Date > DATEADD(DAY,-7,GETDATE())
GROUP BY a.Member,a.Activity
ORDER BY a.Member
Sample ActivityTotals But what we're really looking for here is a more consolidated representation of that. Now, I know I can get there with subqueries doing COUNT(*) for each ActivityType like so
SELECT DISTINCT
a.Member
, (SELECT COUNT(*) FROM v_UpdateActivity WHERE Member = a.Member AND Activity = 'Create' AND Activity_Date > DATEADD(DAY,-7,GETDATE())) As Created
, (SELECT COUNT(*) FROM v_UpdateActivity WHERE Member = a.Member AND Activity = 'Update' AND Activity_Date > DATEADD(DAY,-7,GETDATE())) As Updated
, (SELECT COUNT(*) FROM v_UpdateActivity WHERE Member = a.Member AND Activity = 'Document' AND Activity_Date > DATEADD(DAY,-7,GETDATE())) As Documented
, (SELECT COUNT(*) FROM v_UpdateActivity WHERE Member = a.Member AND Activity = 'Deactivate' AND Activity_Date > DATEADD(DAY,-7,GETDATE())) As Deactivated
, (SELECT COUNT(*) FROM v_UpdateActivity WHERE Member = a.Member AND Activity = 'Reactivate' AND Activity_Date > DATEADD(DAY,-7,GETDATE())) As Reactivated
FROM v_cw_ConfigUpdateActivity a
WHERE a.Activity_Date > DATEADD(DAY,-7,GETDATE())
ORDER BY a.Member
And this does a decent job of getting me the output I want (including zeros for no activity). Desired Output
But (a) this is inefficient - it already doesn't perform well and (b) this just screams aggregation but I am apparently too thick to think of the right way to construct this to get what I'm looking for. Any help?
Upvotes: 1
Views: 30
Reputation: 50034
Instead of subqueries you can use CASE statements and a GROUP BY. Alternatively you could do this with a PIVOT.
SELECT
a.Member
SUM(CASE WHEM Activity = 'Create' THEN 1 ELSE 0 END) as Created,
SUM(CASE WHEM Activity = 'Updated' THEN 1 ELSE 0 END) as Updated,
SUM(CASE WHEM Activity = 'Documented' THEN 1 ELSE 0 END) as Documented,
SUM(CASE WHEM Activity = 'Deactivated' THEN 1 ELSE 0 END) as Deactivated,
SUM(CASE WHEM Activity = 'Reactivated' THEN 1 ELSE 0 END) as Reactivated
FROM v_cw_ConfigUpdateActivity a
WHERE a.Activity_Date > DATEADD(DAY,-7,GETDATE())
GROUP BY a.Member
ORDER BY a.Member;
My tsql skills may be showing their rust here, but this is an attempt at a PIVOT
version of this:
SELECT
Member,
Created,
Updated,
Documented,
Deactivated,
Reactivated
FROM (SELECT Member, Activity FROM v_cw_ConfigUpdateActivity) as SourceTable
PIVOT (COUNT(Activity) FOR Member IN (Created, Updated, Documented, Deactivated, Reactivated) as PivotTable
Upvotes: 2