Reputation: 1204
I am trying to display a list of players from team #1 and the stats to go with them, here are the tables
table 1: players
╔═══════════════════════════╗
║ id | fname | lname | team ║
╠═══════════════════════════╣
║ 1 | Jason | McFee | 1 ║
║ 2 | John | Smith | 1 ║
║ 3 | Jack | Doe | 1 ║
║ 4 | Wayne | Gretzky | 2 ║
╚═══════════════════════════╝
table 2: events_goals
╔═════════════════════════╗
║ id g_id a1_id a2_id ║
╠═════════════════════════╣
║ 1 1 2 3 ║
║ 2 3 1 2 ║
║ 3 2 1 NULL ║
╚═════════════════════════╝
What I want to get is this
Name - being concat from table
Goals - COUNT all the times player id is in g_id column
Assists - COUNT (a1_id) + COUNT (a2_id) all the times playerid is in either of those columns
POINTS - sum of goals + assists
╔══════════════════════════════════════╗
║ id | name | goals | assists | points ║
╠══════════════════════════════════════╣
║ 1 J.McFee 1 2 3 ║
║ 2 J.Smith 1 2 3 ║
║ 3 J.Doe 1 1 2 ║
╚══════════════════════════════════════╝
What I have tried to do
>SELECT id,
>CONCAT_WS(', 'SUBSTR(fname, 1, 1), lname) name,
>FROM players
>WHERE teamid = 1
This gets me a return of the names of all the players on the team with the ID of 1 with there names in proper format no problem.
I can get the count of a single player by using
>SELECT COUNT(g_id) FROM events_goals WHERE id = (playerid)
This returns the correct number of goals for player
However when I go to put it all together the stats are wrong and it only displays 1 row when i know there is supposed to be three
> SELECT a.id,
> CONCAT_WS(', 'SUBSTR(a.fname, 1, 1), a.lname) name,
> (COUNT(b.g_id))goals,
> (COUNT(c.a1_id))a1,
> (COUNT(d.a2_id))a2
> FROM players a
> LEFT JOIN events_goals b ON a.id = b.g_id
> LEFT JOIN events_goals c ON a.id = c.a1_id
> LEFT JOIN events_goals d ON a.id = d.a2_id WHERE teamid = 1
Upvotes: 2
Views: 121
Reputation: 43434
This is the query you're looking for:
SELECT
p.id,
CONCAT_WS(', ', SUBSTR(p.fname, 1, 1), p.lname) name,
COALESCE(eg_goals.goals, 0) goals,
COALESCE(eg_assists1.assists, 0) + COALESCE(eg_assists2.assists, 0) assists,
COALESCE(eg_goals.goals, 0) + COALESCE(eg_assists1.assists, 0) + COALESCE(eg_assists2.assists, 0) points
FROM players p
LEFT JOIN (
SELECT g_id, COUNT(g_id) goals FROM events_goals
GROUP BY g_id
) eg_goals ON p.id = eg_goals.g_id
LEFT JOIN (
SELECT a1_id, COUNT(a1_id) assists FROM events_goals
GROUP BY a1_id
) eg_assists1 ON p.id = eg_assists1.a1_id
LEFT JOIN (
SELECT a2_id, COUNT(a2_id) assists FROM events_goals
GROUP BY a2_id
) eg_assists2 ON p.id = eg_assists2.a2_id
WHERE p.team = 1
You should seriously reconsider redesigning your schema. Having those "events" mixed in the same table lead to horrible and very hard to maintain queries.
Upvotes: 1
Reputation: 2332
Using COALESCE
SELECT a.id,
CONCAT_WS(', ', SUBSTR(a.fname, 1, 1), a.lname) name,
(COUNT(b.g_id)) goals,
((COALESCE(COUNT(c.a1_id),0)) + (COALESCE(COUNT(c.a2_id),0))) assists,
(COUNT(COALESCE(c.a1_id,0)) + COUNT(COALESCE(c.a2_id,0)) + COUNT(COALESCE(b.g_id,0))) points
FROM players a
LEFT JOIN events_goals b ON a.id = b.g_id
LEFT JOIN events_goals c ON a.id = c.a1_id
LEFT JOIN events_goals d ON a.id = d.a2_id
WHERE a.teamid = 1
GROUP BY a.id,
CONCAT_WS(', ', SUBSTR(a.fname, 1, 1), a.lname)
Upvotes: 0
Reputation: 166396
You need to add a GROUP BY (see also SQL GROUP BY Statement)
The GROUP BY statement is used in conjunction with the aggregate functions to group the result-set by one or more columns.
**SQL GROUP BY Syntax**
SELECT column_name, aggregate_function(column_name)
FROM table_name
WHERE column_name operator value
GROUP BY column_name;
SELECT a.id,
CONCAT_WS(', 'SUBSTR(a.fname, 1, 1), a.lname) name,
(COUNT(b.g_id))goals,
(COUNT(c.a1_id))a1,
(COUNT(d.a2_id))a2
FROM players a
LEFT JOIN events_goals b ON a.id = b.g_id
LEFT JOIN events_goals c ON a.id = c.a1_id
LEFT JOIN events_goals d ON a.id = d.a2_id
WHERE teamid = 1
GROUP BY a.id,
CONCAT_WS(', 'SUBSTR(a.fname, 1, 1), a.lname)
Upvotes: 0