I need to extract from my database all the goals scored by a specific player. I have this table design:
MATCH
id | home | away | result | round_id
PLAYER
id | first_name | last_name
GOAL
match_id | player_marker_id | type
GOAL_TYPE
id | description
Essentially the table goal
contains all the goals scored in a match
, the table bound the field match_id
as FK
of match.id
. The field player_marker_id
is a FK
of player.id
, and goal_type
contains all the types that a goal can assume, there is 4 types of status for a goal:
1: first_goal
2: goal
3: pg
4: og
What I need to do is return the top scoring players counting the how many first_goal, goal, pg
. I don't need to return og
because it corresponds to auto goal.
What I did for now:
$sql = $this->db->prepare("SELECT
p.first_name AS player_first_name,
p.last_name AS player_last_name,
COUNT(*) AS goal_scored,
p.id AS player_id
FROM `match` m
INNER JOIN goal g ON g.match_id = m.id
INNER JOIN player p ON g.player_marker_id = p.id
WHERE m.round_id = :round_id AND g.type != 4
GROUP BY p.id
ORDER BY goal_scored DESC, player_last_name DESC");
This query is working but doesn't return the expected result, infact I get:
{
"player_first_name": "Ali",
"player_last_name": "Sowe",
"goal_scored": "21",
"player_id": "246638"
},
{
"player_first_name": "Sindrit",
"player_last_name": "Guri",
"goal_scored": "20",
"player_id": "211786"
},
I would return this output:
{
"player_first_name": "Ali",
"player_last_name": "Sowe",
"goal_scored": "21",
"player_id": "246638",
"first_goal": "19",
"goal": "1",
"pg": "1"
}
I tried also to do this:
$sql = $this->db->prepare("SELECT
p.first_name AS player_first_name,
p.last_name AS player_last_name,
COUNT(*) AS goal_scored,
CASE g.type
WHEN 1 THEN 'first_goal'
WHEN 2 THEN 'goal'
WHEN 3 THEN 'pg'
WHEN 4 THEN 'og'
END AS goal_type,
p.id AS player_id
FROM `match` m
INNER JOIN goal g ON g.match_id = m.id
INNER JOIN player p ON g.player_marker_id = p.id
WHERE m.round_id = :round_id AND g.type != 4
GROUP BY p.id
ORDER BY goal_scored DESC, player_last_name DESC");
But this will return:
SQLSTATE[42000]: Syntax error or access violation: 1055 Expression #4 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'swp.g.type' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
and I guess isn't the correct way to go.
round_id
is the league where the match has played.
You can count only the records of a given goal type by moving the case statement to inside the count aggregate function. Try this:
SELECT
p.first_name AS player_first_name,
p.last_name AS player_last_name,
COUNT(*) AS goal_scored,
COUNT(case when g.type = 1 then 1 else null end) as first_goal,
COUNT(case when g.type = 2 then 1 else null end) as goal,
COUNT(case when g.type = 3 then 1 else null end) as pg,
p.id AS player_id
FROM `match` m
INNER JOIN goal g ON g.match_id = m.id
INNER JOIN player p ON g.player_marker_id = p.id
WHERE m.round_id = :round_id AND g.type != 4
GROUP BY p.id
ORDER BY goal_scored DESC, player_last_name DESC
Well, if you can't find any better solutions, you can always use TOP (in SQL Server), or LIMIT (in MySQL), to specify the number of results returned. I assume the first record returned in your first solution is the correct one. Here is a link to how to use them https://www.w3schools.com/sql/sql_top.asp
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.