I have four different tables user
, user_group
, user_and_groups
and actions
.
Users can be added/removed from user_group
. so one user_group
may contain many users. Table user_and_groups
is a relationship table between user
and user_group
. Actions table contains records actions for user added/removed to user_group
and action
(.i.e. added/removed) performed date. So for every month users count in user_group may vary.
I am using SQL Server and I want to list the total count of users in the user group per month.
Below table column details:
User Table-> userid, details
user_group Table -> groupid, details
user_and_groups Table -> userid, groupid (many to many)
actions Table -> **actionid, action_type, directid, indirectid, action_date**
where directid is user_group_Id, and indirectid is userid.
**Action table dummy data:**
**|actionid|action_type |directid|indirectid|action_date|**
|1 | user_added_in_group |100 |2001 |1-Jan-2012|
|2 | user_added_in_group |100 |2002 |1-Feb-2012|
|3 | user_added_in_group |100 |2003 |1-March-2012|
|4 | user_removed_From_group |100 |2001 |1-March-2012|
|5 | user_added_in_group |100 |2004 |1-April-2012|
|6 | user_added_in_group |100 |2001 |1-April-2012|
Notice in above table userid=2001 was first added in Jan then removed in march and then re-added in April.
I want output for the user_group_id = 100 per month- total count of users.
**Expected output:**
+------+-------+-------+
| Year | Month | Count |
+------+-------+-------+
| 2011 | 12 | 0 |
| 2012 | 01 | 1 |
| 2012 | 02 | 2 |
| 2012 | 03 | 2 |
| 2012 | 04 | 4 |
I am not able to write the SQL query for this. Has anybody written same query?
/****************** start edit *************/**
I think I am very near to answer so posting here the query:
DECLARE @countOfUsersInGroup INT = 223
--(this count is got from user_and_groups relation ship table. which will give count of users in one group at current date)
-- but we need each month's user count in user group - do following
DECLARE @addRemoveActionsPerMonth TABLE (id INT IDENTITY ,cyear INT, cmonth INT, addActionsInMonth INT, removedActionsInMonth INT, sumOfAddNRemovedActionsInMonth INT)
INSERT INTO @addRemoveActionsPerMonth (cyear, cmonth, addActionsInMonth, removedActionsInMonth, sumOfAddNRemovedActionsInMonth)
SELECT *
FROM
(
SELECT YEAR(action_date) as cyear, MONTH(action_date) as cmonth,
COUNT( CASE WHEN action_type like 'user_added_in_group' THEN 1 END ) as addActionsInMonth,
COUNT( CASE WHEN action_type like 'user_removed_From_group' THEN 1 END ) as removedActionsInMonth,
COUNT( CASE WHEN action_type like 'user_removed_From_group' THEN 1 END ) - COUNT( CASE WHEN action_type like 'user_added_in_group' THEN 1 END ) as sumOfAddNRemovedActionsInMonth
FROM dbo.[action_fact]
WHERE direct_object_id = 100 --(group id)
AND action_type like 'user_added_in_group' or action_type like 'user_removed_From_group' -- action is added or removed
GROUP BY year(action_date), Month(action_date)
)
as innerTable
ORDER BY cyear, cmonth
DECLARE @cumulativeCountPerMonth TABLE (id INT , cumulativeCount INT)
INSERT INTO @cumulativeCountPerMonth (id, cumulativeCount)
SELECT id,
(
SELECT sum(sumOfAddNRemovedActionsInMonth)
FROM @addRemoveActionsPerMonth as innerTab
WHERE innerTab.id >= outerTab.id
) as cumulativeCount
FROM @addRemoveActionsPerMonth as outerTab
SELECT actionsData.id, cyear, cmonth, addActionsInMonth, removedActionsInMonth, sumOfAddNRemovedActionsInMonth, cumulativeCount,
@countOfUsersInGroup + cumulativeCount as actualUserCountInMonth
FROM @addRemoveActionsPerMonth as actionsData
INNER JOIN @cumulativeCountPerMonth as cumulativeData ON actionsData.id = cumulativeData.id