A SQL guide for counting friendships from both requester and accepter sides, then returning the user with the most friends.
Problem Restatement
We are given a table called RequestAccepted.
Each row means one friend request was accepted.
| Column | Type | Meaning |
|---|---|---|
requester_id | int | The user who sent the friend request |
accepter_id | int | The user who accepted the friend request |
accept_date | date | The date when the request was accepted |
We need to find the user who has the most friends and return:
| Column | Meaning |
|---|---|
id | The user id |
num | The number of friends that user has |
The test cases guarantee that only one person has the most friends. The problem also asks a follow-up where multiple people may tie for the most friends. The main solution only needs to return one user because the official test cases guarantee a unique answer. Source
Input and Output
Input table:
RequestAcceptedOutput columns:
id, numEach accepted request creates one friendship between two users.
So if this row exists:
requester_id = 1, accepter_id = 2then user 1 has user 2 as a friend, and user 2 has user 1 as a friend.
Both sides must be counted.
Example
Input:
| requester_id | accepter_id | accept_date |
|---|---|---|
| 1 | 2 | 2016-06-03 |
| 1 | 3 | 2016-06-08 |
| 2 | 3 | 2016-06-08 |
| 3 | 4 | 2016-06-09 |
Friend counts:
| User | Friends | Count |
|---|---|---|
| 1 | 2, 3 | 2 |
| 2 | 1, 3 | 2 |
| 3 | 1, 2, 4 | 3 |
| 4 | 3 | 1 |
User 3 has the most friends.
Output:
| id | num |
|---|---|
| 3 | 3 |
First Thought: Count Requesters Only
A first attempt might count how many times each user appears in requester_id.
SELECT requester_id, COUNT(*)
FROM RequestAccepted
GROUP BY requester_id;This is incomplete.
A user can have friends from both sides of the table:
| Role | Meaning |
|---|---|
requester_id | The user sent a request that was accepted |
accepter_id | The user accepted a request from someone else |
Both roles represent friendship.
So we need to count every appearance of a user in either column.
Key Insight
Each accepted request contributes one friend count to both users.
For this row:
| requester_id | accepter_id |
|---|---|
| 1 | 3 |
we should count:
| id | Contribution |
|---|---|
| 1 | 1 |
| 3 | 1 |
The clean way is to convert both columns into one column named id.
We can do that with UNION ALL.
SELECT requester_id AS id
FROM RequestAccepted
UNION ALL
SELECT accepter_id AS id
FROM RequestAcceptedAfter this transformation, each row means:
“This user has one friend contribution.”
Then we group by id and count rows.
Algorithm
First, select all requesters as user ids.
Second, select all accepters as user ids.
Third, combine them with UNION ALL.
Fourth, group by user id and count how many times each user appears.
Fifth, sort by the count in descending order.
Finally, return the first row.
SQL Solution
SELECT
id,
COUNT(*) AS num
FROM (
SELECT requester_id AS id
FROM RequestAccepted
UNION ALL
SELECT accepter_id AS id
FROM RequestAccepted
) AS friends
GROUP BY id
ORDER BY num DESC
LIMIT 1;Code Explanation
The inner query creates one unified list of user ids:
SELECT requester_id AS id
FROM RequestAccepted
UNION ALL
SELECT accepter_id AS id
FROM RequestAcceptedWe use UNION ALL, not UNION.
UNION ALL keeps every row. That matters because every accepted request contributes to the friend count.
If user 3 appears three times across both columns, we need all three appearances to remain.
The outer query groups the unified list:
GROUP BY idThen it counts how many rows each user has:
COUNT(*) AS numThis count is the total number of friends for that user.
Then we sort from largest to smallest:
ORDER BY num DESCBecause the problem guarantees one unique user with the most friends, we can return only the first row:
LIMIT 1Correctness
Each row in RequestAccepted represents one accepted friendship between requester_id and accepter_id.
The inner query emits one row for the requester and one row for the accepter. Therefore, each friendship contributes exactly one count to each of its two users.
After the UNION ALL, every emitted row represents one friend contribution for one user.
The outer query groups these contributions by user id. Therefore, COUNT(*) gives the total number of friends for each user.
Sorting by this count in descending order places the user with the largest friend count first.
Since the test cases guarantee that only one person has the most friends, LIMIT 1 returns exactly the required user and friend count.
Complexity
Let n be the number of rows in RequestAccepted.
| Metric | Value | Why |
|---|---|---|
| Time | O(n log n) | The database groups and sorts user counts |
| Space | O(n) | The derived table contains two rows per friendship |
The derived table has 2n rows because every friendship contributes one row for each user.
Follow-up: Return All Ties
In the real world, multiple users may have the same maximum number of friends.
For that version, we can rank users by friend count and return every user whose rank is 1.
WITH friend_counts AS (
SELECT
id,
COUNT(*) AS num
FROM (
SELECT requester_id AS id
FROM RequestAccepted
UNION ALL
SELECT accepter_id AS id
FROM RequestAccepted
) AS friends
GROUP BY id
),
ranked AS (
SELECT
id,
num,
DENSE_RANK() OVER (ORDER BY num DESC) AS rnk
FROM friend_counts
)
SELECT
id,
num
FROM ranked
WHERE rnk = 1;Testing
Sample data:
CREATE TABLE RequestAccepted (
requester_id INT,
accepter_id INT,
accept_date DATE
);
INSERT INTO RequestAccepted (requester_id, accepter_id, accept_date) VALUES
(1, 2, '2016-06-03'),
(1, 3, '2016-06-08'),
(2, 3, '2016-06-08'),
(3, 4, '2016-06-09');Expected output:
| id | num |
|---|---|
| 3 | 3 |
Additional case:
TRUNCATE TABLE RequestAccepted;
INSERT INTO RequestAccepted (requester_id, accepter_id, accept_date) VALUES
(1, 2, '2020-01-01'),
(2, 3, '2020-01-02'),
(2, 4, '2020-01-03');Friend counts:
| User | Count |
|---|---|
| 1 | 1 |
| 2 | 3 |
| 3 | 1 |
| 4 | 1 |
Expected output:
| id | num |
|---|---|
| 2 | 3 |