0% completed
Problem
Table: Calls
+--------------+----------+
| Column Name | Type |
+--------------+----------+
| caller_id | int |
| recipient_id | int |
| call_time | datetime |
+--------------+----------+
(caller_id, recipient_id, call_time) is the primary key (combination of columns with unique values) for this table.
Each row contains information about the time of a phone call between caller_id and recipient_id.
Problem Definition
Write a solution to report the IDs of the users whose first and last calls on any day were with the same person. Calls are counted regardless of being the caller or the recipient.
Example
Output
Try It Yourself
Solution
To identify users whose first and last calls on any day were with the same person, we need to analyze the Calls
table meticulously. This involves determining the first and last call times for each user on each day and then verifying if both calls were with the same individual. The provided SQL query effectively accomplishes this task through a series of logical steps involving Common Table Expressions (CTEs) and joins.
Approach Overview
-
Extract Unique User IDs:
- Compile a list of all unique users involved in calls, whether as callers or recipients.
-
Determine First and Last Call Times per User per Day:
- For each user and each day, identify the earliest (first) and latest (last) call times.
-
Identify Call Partners for First and Last Calls:
- For the first and last calls determined in the previous step, ascertain who the other party was in each call.
-
Filter Users Based on Call Partner Consistency:
- Select users where the call partner in the first call of the day is the same as that in the last call of the same day.
-
Retrieve Distinct User Details:
- Extract and present the unique
user_id
s that meet the criteria.
- Extract and present the unique
SQL Query
WITH cte AS ( SELECT caller_id AS id FROM Calls UNION SELECT recipient_id AS id FROM Calls ) SELECT DISTINCT t.id AS user_id FROM ( SELECT a.id, DATE(call_time) AS call_date, MIN(call_time) AS first_call, MAX(call_time) AS last_call FROM cte a JOIN Calls c ON a.id = c.caller_id OR a.id = c.recipient_id GROUP BY a.id, DATE(call_time) ) t LEFT JOIN Calls c1 ON c1.call_time = t.first_call LEFT JOIN Calls c2 ON c2.call_time = t.last_call WHERE IF(t.id = c1.caller_id, c1.recipient_id, c1.caller_id) = IF(t.id = c2.caller_id, c2.recipient_id, c2.caller_id) ORDER BY t.id;
Step-by-Step Approach
Step 1: Extract Unique User IDs (cte
)
Compile a list of all unique users involved in calls, whether as callers or recipients.
SQL Snippet:
WITH cte AS ( SELECT caller_id AS id FROM Calls UNION SELECT recipient_id AS id FROM Calls ) SELECT * FROM cte;
Explanation:
SELECT caller_id AS id FROM Calls
: Retrieves all caller IDs and aliases them asid
.UNION SELECT recipient_id AS id FROM Calls
: Retrieves all recipient IDs and aliases them asid
. TheUNION
ensures that eachid
is unique, eliminating duplicates.
Intermediate Output After Step 1 (cte
):
+-----+ | id | +-----+ | 1 | | 3 | | 4 | | 5 | | 8 | | 11 | +-----+
Step 2: Determine First and Last Call Times per User per Day
For each user and each day, identify the earliest (first) and latest (last) call times.
SQL Snippet:
SELECT a.id, DATE(call_time) AS call_date, MIN(call_time) AS first_call, MAX(call_time) AS last_call FROM cte a JOIN Calls c ON a.id = c.caller_id OR a.id = c.recipient_id GROUP BY a.id, DATE(call_time);
Explanation:
JOIN Calls c ON a.id = c.caller_id OR a.id = c.recipient_id
: Associates each user with their corresponding calls, whether they were the caller or the recipient.DATE(call_time) AS call_date
: Extracts the date from thecall_time
to group calls by day.MIN(call_time) AS first_call
: Identifies the earliest call time for each user on each day.MAX(call_time) AS last_call
: Identifies the latest call time for each user on each day.GROUP BY a.id, DATE(call_time)
: Groups the data by user and date to perform the aggregations.
Intermediate Output After Step 2 (t
):
+-----+------------+---------------------+---------------------+ | id | call_date | first_call | last_call | +-----+------------+---------------------+---------------------+ | 1 | 2021-08-11 | 2021-08-11 05:28:44 | 2021-08-11 05:28:44 | | 1 | 2021-08-24 | NULL | NULL | | 1 | 2021-08-30 | NULL | NULL | | 2 | 2021-08-24 | NULL | NULL | | 2 | 2021-08-30 | NULL | NULL | | 3 | 2021-08-17 | 2021-08-17 04:04:15 | 2021-08-17 22:22:22 | | 4 | 2021-08-24 | 2021-08-24 17:46:07 | 2021-08-24 19:57:13 | | 5 | 2021-08-11 | 2021-08-11 05:28:44 | 2021-08-11 05:28:44 | | 8 | 2021-08-17 | 2021-08-17 04:04:15 | 2021-08-17 22:22:22 | | 11 | 2021-08-17 | 2021-08-17 13:07:00 | 2021-08-17 13:07:00 | +-----+------------+---------------------+---------------------+
Step 3: Identify Call Partners for First and Last Calls
For each user and each day, determine who they were speaking with during their first and last calls.
SQL Snippet:
LEFT JOIN Calls c1 ON c1.call_time = t.first_call LEFT JOIN Calls c2 ON c2.call_time = t.last_call WHERE IF(t.id = c1.caller_id, c1.recipient_id, c1.caller_id) = IF(t.id = c2.caller_id, c2.recipient_id, c2.caller_id)
Explanation:
LEFT JOIN Calls c1 ON c1.call_time = t.first_call
:- Joins the
Calls
table to get details of the first call (c1
) for each user on each day.
- Joins the
LEFT JOIN Calls c2 ON c2.call_time = t.last_call
:- Joins the
Calls
table to get details of the last call (c2
) for each user on each day.
- Joins the
IF(t.id = c1.caller_id, c1.recipient_id, c1.caller_id)
:- Determines the other party in the first call. If the user was the caller, it selects the recipient, and vice versa.
IF(t.id = c2.caller_id, c2.recipient_id, c2.caller_id)
:- Determines the other party in the last call similarly.
WHERE ... = ...
:- Ensures that the other party in the first call is the same as that in the last call. If true, the user meets the quiet student criteria for that day.
Intermediate Output After Step 3:
+---------+--------------+ | user_id | call_date | +---------+--------------+ | 1 | 2021-08-11 | | 3 | 2021-08-17 | | 4 | 2021-08-24 | | 5 | 2021-08-11 | | 8 | 2021-08-24 | +---------+--------------+
Step 4: Filter and Retrieve Quiet Students
Select users whose first and last calls on any day were with the same person, ensuring that these users have participated in at least one call.
SQL Query:
WITH cte AS ( SELECT caller_id AS id FROM Calls UNION SELECT recipient_id AS id FROM Calls ), t AS ( SELECT a.id, DATE(call_time) AS call_date, MIN(call_time) AS first_call, MAX(call_time) AS last_call FROM cte a JOIN Calls c ON a.id = c.caller_id OR a.id = c.recipient_id GROUP BY a.id, DATE(call_time) ) SELECT DISTINCT t.id AS user_id FROM t LEFT JOIN Calls c1 ON c1.call_time = t.first_call LEFT JOIN Calls c2 ON c2.call_time = t.last_call WHERE IF(t.id = c1.caller_id, c1.recipient_id, c1.caller_id) = IF(t.id = c2.caller_id, c2.recipient_id, c2.caller_id) ORDER BY t.id;
Explanation:
SELECT DISTINCT
:- Ensures each qualifying
user_id
appears only once in the final result.
- Ensures each qualifying
Final Output:
+---------+ | user_id | +---------+ | 1 | | 4 | | 5 | | 8 | +---------+
.....
.....
.....
Table of Contents
Contents are not accessible
Contents are not accessible
Contents are not accessible
Contents are not accessible
Contents are not accessible