League Statistics - Problem

You're tasked with building a comprehensive league management system that calculates team statistics based on match results. Given two database tables - one containing team information and another with match data - you need to compute detailed performance metrics for each team.

The Teams table contains basic team information:

+----------------+---------+
| Column Name    | Type    |
+----------------+---------+
| team_id        | int     |
| team_name      | varchar |
+----------------+---------+

The Matches table records every game played:

+-----------------+---------+
| Column Name     | Type    |
+-----------------+---------+
| home_team_id    | int     |
| away_team_id    | int     |
| home_team_goals | int     |
| away_team_goals | int     |
+-----------------+---------+

Scoring System:

  • Win: 3 points
  • Draw: 1 point each
  • Loss: 0 points

Your task is to generate a comprehensive statistics table containing:

  • team_name - The team's name
  • matches_played - Total matches (home + away)
  • points - Total points earned
  • goal_for - Goals scored by the team
  • goal_against - Goals conceded by the team
  • goal_diff - Goal difference (goals_for - goals_against)

Results must be ordered by: Points (desc) โ†’ Goal Difference (desc) โ†’ Team Name (asc)

Input & Output

example_1.sql โ€” Basic League Example
$ Input: Teams table:\n+----------+-------------+\n| team_id | team_name |\n+----------+-------------+\n| 10 | Leetcode FC |\n| 20 | NewYork FC |\n| 30 | Atlanta FC |\n| 40 | Chicago FC |\n+----------+-------------+\n\nMatches table:\n+---------------+---------------+-------------------+-------------------+\n| home_team_id | away_team_id | home_team_goals | away_team_goals |\n+---------------+---------------+-------------------+-------------------+\n| 10 | 20 | 3 | 0 |\n| 30 | 10 | 2 | 2 |\n| 10 | 40 | 4 | 1 |\n| 20 | 30 | 1 | 5 |\n| 40 | 20 | 2 | 1 |\n+---------------+---------------+-------------------+-------------------+
โ€บ Output: +--------------+----------------+--------+-----------+--------------+-----------+\n| team_name | matches_played | points | goal_for | goal_against | goal_diff |\n+--------------+----------------+--------+-----------+--------------+-----------+\n| Leetcode FC | 3 | 7 | 9 | 3 | 6 |\n| Atlanta FC | 2 | 4 | 7 | 3 | 4 |\n| Chicago FC | 2 | 3 | 3 | 6 | -3 |\n| NewYork FC | 3 | 0 | 2 | 8 | -6 |\n+--------------+----------------+--------+-----------+--------------+-----------+
๐Ÿ’ก Note: Leetcode FC played 3 matches (2 home, 1 away), won 2 games (6 points) and drew 1 (1 point) for 7 total points. They scored 9 goals (3+2+4) and conceded 3 (0+2+1). Atlanta FC had 1 win and 1 draw for 4 points. The teams are ordered by points descending, then goal difference descending.
example_2.sql โ€” Tie-Breaking Example
$ Input: Teams table:\n+----------+-------------+\n| team_id | team_name |\n+----------+-------------+\n| 1 | Arsenal |\n| 2 | Chelsea |\n| 3 | Liverpool |\n+----------+-------------+\n\nMatches table:\n+---------------+---------------+-------------------+-------------------+\n| home_team_id | away_team_id | home_team_goals | away_team_goals |\n+---------------+---------------+-------------------+-------------------+\n| 1 | 2 | 2 | 1 |\n| 2 | 3 | 1 | 1 |\n| 3 | 1 | 0 | 3 |\n+---------------+---------------+-------------------+-------------------+
โ€บ Output: +-----------+----------------+--------+-----------+--------------+-----------+\n| team_name | matches_played | points | goal_for | goal_against | goal_diff |\n+-----------+----------------+--------+-----------+--------------+-----------+\n| Arsenal | 2 | 6 | 5 | 1 | 4 |\n| Chelsea | 2 | 1 | 2 | 3 | -1 |\n| Liverpool | 2 | 1 | 1 | 4 | -3 |\n+-----------+----------------+--------+-----------+--------------+-----------+
๐Ÿ’ก Note: Arsenal wins both matches for 6 points. Chelsea and Liverpool both have 1 point, but Chelsea has better goal difference (-1 vs -3), so Chelsea ranks higher. This demonstrates the tie-breaking rules in action.
example_3.sql โ€” Team With No Matches
$ Input: Teams table:\n+----------+-------------+\n| team_id | team_name |\n+----------+-------------+\n| 1 | Real Madrid |\n| 2 | Barcelona |\n| 3 | Atletico |\n+----------+-------------+\n\nMatches table:\n+---------------+---------------+-------------------+-------------------+\n| home_team_id | away_team_id | home_team_goals | away_team_goals |\n+---------------+---------------+-------------------+-------------------+\n| 1 | 2 | 1 | 3 |\n+---------------+---------------+-------------------+-------------------+
โ€บ Output: +--------------+----------------+--------+-----------+--------------+-----------+\n| team_name | matches_played | points | goal_for | goal_against | goal_diff |\n+--------------+----------------+--------+-----------+--------------+-----------+\n| Barcelona | 1 | 3 | 3 | 1 | 2 |\n| Atletico | 0 | 0 | 0 | 0 | 0 |\n| Real Madrid | 1 | 0 | 1 | 3 | -2 |\n+--------------+----------------+--------+-----------+--------------+-----------+
๐Ÿ’ก Note: Atletico hasn't played any matches, so all their statistics are 0. Barcelona wins their match against Real Madrid. This shows how teams with no matches are handled (using COALESCE to default to 0) and the final alphabetical ordering tie-breaker.

Visualization

Tap to expand
League Statistics Calculation ProcessFrom Match Results to Final StandingsStep 1: Raw MatchesMatch 1: TeamA(H) 2-1 TeamB(A)Match 2: TeamB(H) 0-0 TeamC(A)Match 3: TeamC(H) 3-2 TeamA(A)Step 2: Split RecordsTeamA: 1 match, 3pts, 2-1TeamB: 1 match, 0pts, 1-2TeamB: 1 match, 1pt, 0-0TeamC: 1 match, 1pt, 0-0Step 3: UNION ALLCombine home + awayrecords into singleunified datasetStep 4: GROUP BY TeamAggregate all recordsfor each teamSUM(matches, points, goals)Step 5: Final League TableTeamA: 2 matches, 3 pts, 5 goals for, 4 against, +1 diffTeamB: 2 matches, 1 pt, 1 goal for, 2 against, -1 diffTeamC: 2 matches, 4 pts, 3 goals for, 2 against, +1 diff๐ŸŽฏ Key Insight: Single Pass + UNION ALL + GROUP BY = O(n) EfficiencyWhy This Approach Worksโœ… Efficient: Only one pass through matches tableโœ… Clear Logic: Separate home/away processing makes code readableโœ… Scalable: Performance remains good even with large datasetsโœ… Complete: Handles teams with no matches (COALESCE)โœ… Sorted: Proper ordering by points โ†’ goal diff โ†’ nameโœ… Standard SQL: Uses common CTE pattern
Understanding the Visualization
1
Split Each Match
For every match, create two records - one for home team performance and one for away team performance
2
Calculate Points
Assign 3 points for wins, 1 point for draws, 0 points for losses based on goal comparison
3
Track Goals
Record goals scored (goal_for) and goals conceded (goal_against) for each team in each match
4
Combine with UNION
Merge all home team records with all away team records into one dataset
5
Aggregate by Team
Group by team_id and sum up matches_played, points, goal_for, and goal_against
6
Final Rankings
Sort by points (desc), goal difference (desc), then team name (asc) to get final standings
Key Takeaway
๐ŸŽฏ Key Insight: Treat each match as generating two separate team records (home and away), then aggregate them using GROUP BY. This single-pass approach with UNION ALL is far more efficient than multiple subqueries and results in clean, maintainable SQL code.

Time & Space Complexity

Time Complexity
โฑ๏ธ
O(n)

Single pass through matches table plus sorting

n
2n
โœ“ Linear Growth
Space Complexity
O(n)

Space for CTE results and final aggregation

n
2n
โšก Linearithmic Space

Constraints

  • 1 โ‰ค Number of teams โ‰ค 1000
  • 0 โ‰ค Number of matches โ‰ค 104
  • 0 โ‰ค home_team_goals, away_team_goals โ‰ค 100
  • Each match has exactly two different teams
  • All team_id values in Matches table exist in Teams table
Asked in
Amazon 45 Microsoft 38 Google 32 Meta 28
42.3K Views
High Frequency
~25 min Avg. Time
1.8K Likes
Ln 1, Col 1
Smart Actions
๐Ÿ’ก Explanation
AI Ready
๐Ÿ’ก Suggestion Tab to accept Esc to dismiss
// Output will appear here after running code
Code Editor Closed
Click the red button to reopen