{ "data": { "question": { "questionId": "4103", "questionFrontendId": "3716", "categoryTitle": "Database", "boundTopicId": 3805185, "title": "Find Churn Risk Customers", "titleSlug": "find-churn-risk-customers", "content": "

Table: subscription_events

\n\n
\n+------------------+---------+\n| Column Name      | Type    | \n+------------------+---------+\n| event_id         | int     |\n| user_id          | int     |\n| event_date       | date    |\n| event_type       | varchar |\n| plan_name        | varchar |\n| monthly_amount   | decimal |\n+------------------+---------+\nevent_id is the unique identifier for this table.\nevent_type can be start, upgrade, downgrade, or cancel.\nplan_name can be basic, standard, premium, or NULL (when event_type is cancel).\nmonthly_amount represents the monthly subscription cost after this event.\nFor cancel events, monthly_amount is 0.\n
\n\n

Write a solution to Find Churn Risk Customers - users who show warning signs before churning. A user is considered churn risk customer if they meet ALL the following criteria:

\n\n\n\n

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

\n\n

The result format is in the following example.

\n\n

 

\n

Example:

\n\n
\n

Input:

\n\n

subscription_events table:

\n\n
\n+----------+---------+------------+------------+-----------+----------------+\n| event_id | user_id | event_date | event_type | plan_name | monthly_amount |\n+----------+---------+------------+------------+-----------+----------------+\n| 1        | 501     | 2024-01-01 | start      | premium   | 29.99          |\n| 2        | 501     | 2024-02-15 | downgrade  | standard  | 19.99          |\n| 3        | 501     | 2024-03-20 | downgrade  | basic     | 9.99           |\n| 4        | 502     | 2024-01-05 | start      | standard  | 19.99          |\n| 5        | 502     | 2024-02-10 | upgrade    | premium   | 29.99          |\n| 6        | 502     | 2024-03-15 | downgrade  | basic     | 9.99           |\n| 7        | 503     | 2024-01-10 | start      | basic     | 9.99           |\n| 8        | 503     | 2024-02-20 | upgrade    | standard  | 19.99          |\n| 9        | 503     | 2024-03-25 | upgrade    | premium   | 29.99          |\n| 10       | 504     | 2024-01-15 | start      | premium   | 29.99          |\n| 11       | 504     | 2024-03-01 | downgrade  | standard  | 19.99          |\n| 12       | 504     | 2024-03-30 | cancel     | NULL      | 0.00           |\n| 13       | 505     | 2024-02-01 | start      | basic     | 9.99           |\n| 14       | 505     | 2024-02-28 | upgrade    | standard  | 19.99          |\n| 15       | 506     | 2024-01-20 | start      | premium   | 29.99          |\n| 16       | 506     | 2024-03-10 | downgrade  | basic     | 9.99           |\n+----------+---------+------------+------------+-----------+----------------+\n
\n\n

Output:

\n\n
\n+----------+--------------+------------------------+-----------------------+--------------------+\n| user_id  | current_plan | current_monthly_amount | max_historical_amount | days_as_subscriber |\n+----------+--------------+------------------------+-----------------------+--------------------+\n| 501      | basic        | 9.99                   | 29.99                 | 79                 |\n| 502      | basic        | 9.99                   | 29.99                 | 69                 |\n+----------+--------------+------------------------+-----------------------+--------------------+\n
\n\n

Explanation:

\n\n\n\n

Result table is ordered by days_as_subscriber DESC, then user_id ASC.

\n\n

Note: days_as_subscriber is calculated from the first event date to the last event date for each user.

\n
\n", "translatedTitle": "寻找流失风险客户", "translatedContent": "

表:subscription_events

\n\n
\n+------------------+---------+\n| Column Name      | Type    | \n+------------------+---------+\n| event_id         | int     |\n| user_id          | int     |\n| event_date       | date    |\n| event_type       | varchar |\n| plan_name        | varchar |\n| monthly_amount   | decimal |\n+------------------+---------+\nevent_id 是这张表的唯一主键。\nevent_type 可以是 start,upgrade,downgrade 或 cancel。\nplan_name 可以是 basic,standard,premium 或 NULL(当 event_type 是 cancel)。\nmonthly_amount 表示此次事件后的月度订阅费用。\n对于 cancel 的事件,monthly_amount 为 0。\n
\n\n

编写一个解决方案来 寻找流失风险用户 - 出现预流失信号的用户。如果用户符合以下所有条件,则被视为 有流失风险 的客户:

\n\n\n\n

返回结果表按 days_as_subscriber 降序 排序,然后按 user_id 升序 排序。

\n\n

结果格式如下所示。

\n\n

 

\n\n

示例:

\n\n
\n

输入:

\n\n

subscription_events 表:

\n\n
\n+----------+---------+------------+------------+-----------+----------------+\n| event_id | user_id | event_date | event_type | plan_name | monthly_amount |\n+----------+---------+------------+------------+-----------+----------------+\n| 1        | 501     | 2024-01-01 | start      | premium   | 29.99          |\n| 2        | 501     | 2024-02-15 | downgrade  | standard  | 19.99          |\n| 3        | 501     | 2024-03-20 | downgrade  | basic     | 9.99           |\n| 4        | 502     | 2024-01-05 | start      | standard  | 19.99          |\n| 5        | 502     | 2024-02-10 | upgrade    | premium   | 29.99          |\n| 6        | 502     | 2024-03-15 | downgrade  | basic     | 9.99           |\n| 7        | 503     | 2024-01-10 | start      | basic     | 9.99           |\n| 8        | 503     | 2024-02-20 | upgrade    | standard  | 19.99          |\n| 9        | 503     | 2024-03-25 | upgrade    | premium   | 29.99          |\n| 10       | 504     | 2024-01-15 | start      | premium   | 29.99          |\n| 11       | 504     | 2024-03-01 | downgrade  | standard  | 19.99          |\n| 12       | 504     | 2024-03-30 | cancel     | NULL      | 0.00           |\n| 13       | 505     | 2024-02-01 | start      | basic     | 9.99           |\n| 14       | 505     | 2024-02-28 | upgrade    | standard  | 19.99          |\n| 15       | 506     | 2024-01-20 | start      | premium   | 29.99          |\n| 16       | 506     | 2024-03-10 | downgrade  | basic     | 9.99           |\n+----------+---------+------------+------------+-----------+----------------+\n
\n\n

输出:

\n\n
\n+----------+--------------+------------------------+-----------------------+--------------------+\n| user_id  | current_plan | current_monthly_amount | max_historical_amount | days_as_subscriber |\n+----------+--------------+------------------------+-----------------------+--------------------+\n| 501      | basic        | 9.99                   | 29.99                 | 79                 |\n| 502      | basic        | 9.99                   | 29.99                 | 69                 |\n+----------+--------------+------------------------+-----------------------+--------------------+\n
\n\n

解释:

\n\n\n\n

结果表按 days_as_subscriber 降序排序,然后按 user_id 升序排序。

\n\n

注意:days_as_subscriber 按照每个用户的第一个事件日期到最后一个事件日期进行计算。

\n
\n", "isPaidOnly": false, "difficulty": "Medium", "likes": 0, "dislikes": 0, "isLiked": null, "similarQuestions": "[]", "contributors": [], "langToValidPlayground": "{\"cpp\": false, \"java\": false, \"python3\": false, \"python\": false, \"javascript\": false, \"typescript\": false, \"csharp\": false, \"c\": false, \"golang\": false, \"kotlin\": false, \"swift\": false, \"rust\": false, \"ruby\": false, \"php\": false, \"dart\": false, \"scala\": false, \"elixir\": false, \"erlang\": false, \"racket\": false, \"cangjie\": false, \"bash\": false, \"html\": false, \"pythonml\": false, \"react\": false, \"vanillajs\": false, \"mysql\": false, \"mssql\": false, \"postgresql\": false, \"oraclesql\": false, \"pythondata\": false}", "topicTags": [], "companyTagStats": null, "codeSnippets": [ { "lang": "MySQL", "langSlug": "mysql", "code": "# Write your MySQL query statement below", "__typename": "CodeSnippetNode" }, { "lang": "MS SQL Server", "langSlug": "mssql", "code": "/* Write your T-SQL query statement below */", "__typename": "CodeSnippetNode" }, { "lang": "PostgreSQL", "langSlug": "postgresql", "code": "-- Write your PostgreSQL query statement below", "__typename": "CodeSnippetNode" }, { "lang": "Oracle", "langSlug": "oraclesql", "code": "/* Write your PL/SQL query statement below */", "__typename": "CodeSnippetNode" }, { "lang": "Pandas", "langSlug": "pythondata", "code": "import pandas as pd\n\ndef find_churn_risk_customers(subscription_events: pd.DataFrame) -> pd.DataFrame:\n ", "__typename": "CodeSnippetNode" } ], "stats": "{\"totalAccepted\": \"124\", \"totalSubmission\": \"165\", \"totalAcceptedRaw\": 124, \"totalSubmissionRaw\": 165, \"acRate\": \"75.2%\"}", "hints": [], "solution": null, "status": null, "sampleTestCase": "{\"headers\":{\"subscription_events\":[\"event_id\",\"user_id\",\"event_date\",\"event_type\",\"plan_name\",\"monthly_amount\"]},\"rows\":{\"subscription_events\":[[1,501,\"2024-01-01\",\"start\",\"premium\",29.99],[2,501,\"2024-02-15\",\"downgrade\",\"standard\",19.99],[3,501,\"2024-03-20\",\"downgrade\",\"basic\",9.99],[4,502,\"2024-01-05\",\"start\",\"standard\",19.99],[5,502,\"2024-02-10\",\"upgrade\",\"premium\",29.99],[6,502,\"2024-03-15\",\"downgrade\",\"basic\",9.99],[7,503,\"2024-01-10\",\"start\",\"basic\",9.99],[8,503,\"2024-02-20\",\"upgrade\",\"standard\",19.99],[9,503,\"2024-03-25\",\"upgrade\",\"premium\",29.99],[10,504,\"2024-01-15\",\"start\",\"premium\",29.99],[11,504,\"2024-03-01\",\"downgrade\",\"standard\",19.99],[12,504,\"2024-03-30\",\"cancel\",null,0.00],[13,505,\"2024-02-01\",\"start\",\"basic\",9.99],[14,505,\"2024-02-28\",\"upgrade\",\"standard\",19.99],[15,506,\"2024-01-20\",\"start\",\"premium\",29.99],[16,506,\"2024-03-10\",\"downgrade\",\"basic\",9.99]]}}", "metaData": "{\"mysql\":[\"CREATE TABLE if not exists subscription_events (\\n event_id INT,\\n user_id INT,\\n event_date DATE,\\n event_type VARCHAR(20),\\n plan_name VARCHAR(20),\\n monthly_amount DECIMAL(10,2)\\n)\"],\"mssql\":[\"CREATE TABLE subscription_events (\\n event_id INT,\\n user_id INT,\\n event_date DATE,\\n event_type VARCHAR(20),\\n plan_name VARCHAR(20),\\n monthly_amount DECIMAL(10,2)\\n)\"],\"oraclesql\":[\"CREATE TABLE subscription_events (\\n event_id NUMBER,\\n user_id NUMBER,\\n event_date DATE,\\n event_type VARCHAR2(20),\\n plan_name VARCHAR2(20),\\n monthly_amount NUMBER(10,2)\\n)\",\"ALTER SESSION SET nls_date_format='YYYY-MM-DD'\"],\"database\":true,\"name\":\"find_churn_risk_customers\",\"postgresql\":[\"CREATE TABLE IF NOT EXISTS subscription_events (\\n event_id INT PRIMARY KEY,\\n user_id INT NOT NULL,\\n event_date DATE NOT NULL,\\n event_type VARCHAR(20) NOT NULL,\\n plan_name VARCHAR(20),\\n monthly_amount NUMERIC(10,2) NOT NULL\\n);\\n\"],\"pythondata\":[\"subscription_events = pd.DataFrame({\\n \\\"event_id\\\": pd.Series(dtype=\\\"int\\\"),\\n \\\"user_id\\\": pd.Series(dtype=\\\"int\\\"),\\n \\\"event_date\\\": pd.Series(dtype=\\\"datetime64[ns]\\\"), # corresponds to SQL DATE\\n \\\"event_type\\\": pd.Series(dtype=\\\"string\\\"),\\n \\\"plan_name\\\": pd.Series(dtype=\\\"string\\\"), # can be NULL for cancel events\\n \\\"monthly_amount\\\": pd.Series(dtype=\\\"float\\\") # corresponds to DECIMAL(10,2)\\n})\"],\"database_schema\":{\"subscription_events\":{\"event_id\":\"INT\",\"user_id\":\"INT\",\"event_date\":\"DATE\",\"event_type\":\"VARCHAR(20)\",\"plan_name\":\"VARCHAR(20)\",\"monthly_amount\":\"DECIMAL(10, 2)\"}}}", "judgerAvailable": true, "judgeType": "large", "mysqlSchemas": [ "CREATE TABLE if not exists subscription_events (\n event_id INT,\n user_id INT,\n event_date DATE,\n event_type VARCHAR(20),\n plan_name VARCHAR(20),\n monthly_amount DECIMAL(10,2)\n)", "Truncate table subscription_events", "insert into subscription_events (event_id, user_id, event_date, event_type, plan_name, monthly_amount) values ('1', '501', '2024-01-01', 'start', 'premium', '29.99')", "insert into subscription_events (event_id, user_id, event_date, event_type, plan_name, monthly_amount) values ('2', '501', '2024-02-15', 'downgrade', 'standard', '19.99')", "insert into subscription_events (event_id, user_id, event_date, event_type, plan_name, monthly_amount) values ('3', '501', '2024-03-20', 'downgrade', 'basic', '9.99')", "insert into subscription_events (event_id, user_id, event_date, event_type, plan_name, monthly_amount) values ('4', '502', '2024-01-05', 'start', 'standard', '19.99')", "insert into subscription_events (event_id, user_id, event_date, event_type, plan_name, monthly_amount) values ('5', '502', '2024-02-10', 'upgrade', 'premium', '29.99')", "insert into subscription_events (event_id, user_id, event_date, event_type, plan_name, monthly_amount) values ('6', '502', '2024-03-15', 'downgrade', 'basic', '9.99')", "insert into subscription_events (event_id, user_id, event_date, event_type, plan_name, monthly_amount) values ('7', '503', '2024-01-10', 'start', 'basic', '9.99')", "insert into subscription_events (event_id, user_id, event_date, event_type, plan_name, monthly_amount) values ('8', '503', '2024-02-20', 'upgrade', 'standard', '19.99')", "insert into subscription_events (event_id, user_id, event_date, event_type, plan_name, monthly_amount) values ('9', '503', '2024-03-25', 'upgrade', 'premium', '29.99')", "insert into subscription_events (event_id, user_id, event_date, event_type, plan_name, monthly_amount) values ('10', '504', '2024-01-15', 'start', 'premium', '29.99')", "insert into subscription_events (event_id, user_id, event_date, event_type, plan_name, monthly_amount) values ('11', '504', '2024-03-01', 'downgrade', 'standard', '19.99')", "insert into subscription_events (event_id, user_id, event_date, event_type, plan_name, monthly_amount) values ('12', '504', '2024-03-30', 'cancel', NULL, '0.0')", "insert into subscription_events (event_id, user_id, event_date, event_type, plan_name, monthly_amount) values ('13', '505', '2024-02-01', 'start', 'basic', '9.99')", "insert into subscription_events (event_id, user_id, event_date, event_type, plan_name, monthly_amount) values ('14', '505', '2024-02-28', 'upgrade', 'standard', '19.99')", "insert into subscription_events (event_id, user_id, event_date, event_type, plan_name, monthly_amount) values ('15', '506', '2024-01-20', 'start', 'premium', '29.99')", "insert into subscription_events (event_id, user_id, event_date, event_type, plan_name, monthly_amount) values ('16', '506', '2024-03-10', 'downgrade', 'basic', '9.99')" ], "enableRunCode": true, "envInfo": "{\"mysql\":[\"MySQL\",\"

\\u7248\\u672c\\uff1aMySQL 8.0<\\/code><\\/p>\"],\"mssql\":[\"MS SQL Server\",\"

mssql server 2019.<\\/p>\"],\"oraclesql\":[\"Oracle\",\"

Oracle Sql 11.2.<\\/p>\"],\"pythondata\":[\"Pandas\",\"

Python 3.10 with Pandas 2.2.2 and NumPy 1.26.4<\\/p>\"],\"postgresql\":[\"PostgreSQL\",\"

PostgreSQL 16<\\/p>\"]}", "book": null, "isSubscribed": false, "isDailyQuestion": false, "dailyRecordStatus": null, "editorType": "CKEDITOR", "ugcQuestionId": null, "style": "LEETCODE", "exampleTestcases": "{\"headers\":{\"subscription_events\":[\"event_id\",\"user_id\",\"event_date\",\"event_type\",\"plan_name\",\"monthly_amount\"]},\"rows\":{\"subscription_events\":[[1,501,\"2024-01-01\",\"start\",\"premium\",29.99],[2,501,\"2024-02-15\",\"downgrade\",\"standard\",19.99],[3,501,\"2024-03-20\",\"downgrade\",\"basic\",9.99],[4,502,\"2024-01-05\",\"start\",\"standard\",19.99],[5,502,\"2024-02-10\",\"upgrade\",\"premium\",29.99],[6,502,\"2024-03-15\",\"downgrade\",\"basic\",9.99],[7,503,\"2024-01-10\",\"start\",\"basic\",9.99],[8,503,\"2024-02-20\",\"upgrade\",\"standard\",19.99],[9,503,\"2024-03-25\",\"upgrade\",\"premium\",29.99],[10,504,\"2024-01-15\",\"start\",\"premium\",29.99],[11,504,\"2024-03-01\",\"downgrade\",\"standard\",19.99],[12,504,\"2024-03-30\",\"cancel\",null,0.00],[13,505,\"2024-02-01\",\"start\",\"basic\",9.99],[14,505,\"2024-02-28\",\"upgrade\",\"standard\",19.99],[15,506,\"2024-01-20\",\"start\",\"premium\",29.99],[16,506,\"2024-03-10\",\"downgrade\",\"basic\",9.99]]}}", "__typename": "QuestionNode" } } }