Reputation: 35
Let's say I have a two tables in my Oracle database...
One table stores when a new collection is added
+---------------+----------------------+
| collection_id | created_ts |
+---------------+----------------------+
| 001 | 02-JAN-2019 19:40:47 |
| 002 | 04-JAN-2019 00:05:05 |
+---------------+----------------------+
The other table stores each action a user takes against a collection
+---------------+---------------------------------+
| collection_id | action_ts |
+---------------+---------------------------------+
| 001 | 02-JAN-19 07.41.08.869000000 PM |
| 001 | 02-JAN-19 07.41.29.440000000 PM |
| 001 | 02-JAN-19 08.34.42.097000000 PM |
| 001 | 02-JAN-19 09.27.02.433000000 PM |
| 001 | 03-JAN-19 03.54.42.098000000 PM |
| 001 | 07-JAN-19 08.04.55.075000000 PM |
| 001 | 08-JAN-19 07.29.38.727000000 PM |
+---------------+---------------------------------+
My goal is to determine a daily action count for each collection for up to 2 days after the collection is created.
The example output would look something like
+---------------+----------------+----------------------+----------------------+
| collection_id | actions_day_of | actions_1_days_after | actions_2_days_after |
+---------------+----------------+----------------------+----------------------+
| 001 | 4 | 1 | 0 |
+---------------+----------------+----------------------+----------------------+
Is there some combination of counts and case statements I can use to get this output, or does this have to be some union of 7 separate queries to handle all possible days of the week a collection could be created?
Upvotes: 0
Views: 98
Reputation: 1270883
I would just use conditional aggregation:
SELECT T1.COLLECTION_ID,
(CASE WHEN TRUNC(T2.ACTION_TS) = TRUNC(T1.CREATED_TS)
THEN 1 ELSE 0
END) as actions_day_of,
(CASE WHEN TRUNC(T2.ACTION_TS) = TRUNC(T1.CREATED_TS) + INTERVAL '1' DAY
THEN 1 ELSE 0
END) as actions_1_day_after,
(CASE WHEN TRUNC(T2.ACTION_TS) = TRUNC(T1.CREATED_TS) + INTERVAL '2' DAY
THEN 1 ELSE 0
END) as actions_2_day_after,
(CASE WHEN TRUNC(T2.ACTION_TS) > TRUNC(T1.CREATED_TS) + INTERVAL '2' DAY
THEN 1 ELSE 0
END) as actions_2plus_days_after
TABLE2 T2
ON T1.COLLECTION_ID = T2.COLLECTION_ID
GROUP BY T1.COLLECTION_ID;
Notice the last column. It is much simpler to have inequalities compared to PIVOT
.
Upvotes: 0
Reputation: 35930
You can take advantage of the PIVOT
for achieving the desired result.
SELECT * FROM
( SELECT T1.COLLECTION_ID,
TRUNC(T2.ACTION_TS) - TRUNC(T1.CREATED_TS) AS DIFF
FROM TABLE1 T1
JOIN TABLE2 T2 ON T1.COLLECTION_ID = T2.COLLECTION_ID
) PIVOT (
COUNT ( 1 )
FOR DIFF IN ( 0 AS ACTIONS_DAY_OF,
1 AS ACTIONS_1_DAYS_AFTER,
2 AS ACTIONS_2_DAYS_AFTER )
)
Cheers!!
Upvotes: 2