Description
Table: UserActivity
+---------------+---------+
| Column Name | Type |
+---------------+---------+
| username | varchar |
| activity | varchar |
| startDate | Date |
| endDate | Date |
+---------------+---------+
There is no primary key for this table. It may contain duplicates.
This table contains information about the activity performed by each user in a period of time.
A person with username performed an activity from startDate to endDate.
Write an SQL query to show the second most recent activity of each user.
If the user only has one activity, return that one. A user cannot perform more than one activity at the same time.
Return the result table in any order.
SQL Schema
Create table If Not Exists UserActivity (username varchar(30), activity varchar(30), startDate date, endDate date)
Truncate table UserActivity
insert into UserActivity (username, activity, startDate, endDate) values ('Alice', 'Travel', '2020-02-12', '2020-02-20')
insert into UserActivity (username, activity, startDate, endDate) values ('Alice', 'Dancing', '2020-02-21', '2020-02-23')
insert into UserActivity (username, activity, startDate, endDate) values ('Alice', 'Travel', '2020-02-24', '2020-02-28')
insert into UserActivity (username, activity, startDate, endDate) values ('Bob', 'Travel', '2020-02-11', '2020-02-18')
Idea
The query result format is in the following example.
+------------+--------------+-------------+-------------+
| username | activity | startDate | endDate |
+------------+--------------+-------------+-------------+
| Alice | Dancing | 2020-02-21 | 2020-02-23 |
| Bob | Travel | 2020-02-11 | 2020-02-18 |
+------------+--------------+-------------+-------------+
Fulfill requirements :
- To generate a rank table order by
endDateof each user via functionrank()asrn. It will help to find user who has at least twice activity records in tableUserActivity.
Name thiswith clauseasrank_end_date. - Find
_second mostly recent activity_record of each user fromrand_end_date. User will be missing who has only one activity record.
Name thiswith clauseasactivity_twice. - Find users who has only once activity record of table
UserActivity. Using left joinactivity_twiceto rule out users who has been listing intwice_record.
Name thiswith clauseasactivity_once. - Finally,
unionthe result ofactivity_twiceandtwice_recordfor output of the query.
Solution
with
rank_end_date as (
select
rank() over(partition by username order by endDate desc) as rn,
username,
activity,
startDate,
endDate
from useractivity
),
activity_twice as (
select
rn, username, activity, startDate, endDate
from rank_end_date
where rn = 2
),
activity_once as (
select
a.rn, a.username, a.activity, a.startDate, a.endDate
from rank_end_date a
left join activity_twice b using(username)
where ifnull(b.rn, 0) = 0
)
select username, activity, startDate, endDate from activity_once
union
select username, activity, startDate, endDate from activity_twice