LeetCode-in-Java

3832. Find Users with Persistent Behavior Patterns

Hard

Table: activity

+--------------+---------+
| Column Name  | Type    |
+--------------+---------+
| user_id      | int     |
| action_date  | date    |
| action       | varchar |
+--------------+---------+

(user_id, action_date, action) is the primary key (unique value) for this table. Each row represents a user performing a specific action on a given date.

Write a solution to identify behaviorally stable users based on the following definition:

Return the result table ordered by streak_length in descending order, then by user_id in ascending order.

The result format is in the following example.

Example:

Input:

activity table:

+---------+-------------+--------+
| user_id | action_date | action |
+---------+-------------+--------+
| 1       | 2024-01-01  | login  |
| 1       | 2024-01-02  | login  |
| 1       | 2024-01-03  | login  |
| 1       | 2024-01-04  | login  |
| 1       | 2024-01-05  | login  |
| 1       | 2024-01-06  | logout |
| 2       | 2024-01-01  | click  |
| 2       | 2024-01-02  | click  |
| 2       | 2024-01-03  | click  |
| 2       | 2024-01-04  | click  |
| 3       | 2024-01-01  | view   |
| 3       | 2024-01-02  | view   |
| 3       | 2024-01-03  | view   |
| 3       | 2024-01-04  | view   |
| 3       | 2024-01-05  | view   |
| 3       | 2024-01-06  | view   |
| 3       | 2024-01-07  | view   |
+---------+-------------+--------+

Output:

+---------+--------+---------------+------------+------------+
| user_id | action | streak_length | start_date | end_date   |
+---------+--------+---------------+------------+------------+
| 3       | view   | 7             | 2024-01-01 | 2024-01-07 |
| 1       | login  | 5             | 2024-01-01 | 2024-01-05 |
+---------+--------+---------------+------------+------------+

Explanation:

The Results table is ordered by streak_length in descending order, then by user_id in ascending order.

Solution

# Write your MySQL query statement below
WITH distinct_activity AS (
    SELECT DISTINCT
        user_id,
        action,
        action_date
    FROM activity
),
numbered_activity AS (
    SELECT
        user_id,
        action,
        action_date,
        DATEADD(
            'DAY',
            -ROW_NUMBER() OVER (
                PARTITION BY user_id, action
                ORDER BY action_date
            ),
            action_date
        ) AS streak_group
    FROM distinct_activity
),
streaks AS (
    SELECT
        user_id,
        action,
        COUNT(*) AS streak_length,
        MIN(action_date) AS start_date,
        MAX(action_date) AS end_date
    FROM numbered_activity
    GROUP BY
        user_id,
        action,
        streak_group
    HAVING COUNT(*) >= 5
),
ranked_streaks AS (
    SELECT
        user_id,
        action,
        streak_length,
        start_date,
        end_date,
        ROW_NUMBER() OVER (
            PARTITION BY user_id
            ORDER BY
                streak_length DESC,
                end_date DESC,
                action ASC
        ) AS priority
    FROM streaks
)
SELECT
    user_id,
    action,
    streak_length,
    start_date,
    end_date
FROM ranked_streaks
WHERE priority = 1
ORDER BY
    streak_length DESC,
    user_id ASC;