I'm having trouble getting the count of rows from a specific table on two separate conditions for rows from a main table :
Mainly, I've got a table for players, with simple 开发者_如何学JAVAinformations, like playername and id. I've got also a table with action, where each player is listed with the type of the action (goal or assist). I want to get all players with a column counting their goals, and another counting their assists. Of course, I want the lazy players, whom haven't score any goals, or made any assists.
For now I came up with this request, but it only gives me the best players, whereas i want all players. Please light my mind ;)
SELECT
`p`.`playername`,
COUNT(`a1`.`actionid`) AS `goals`,
COUNT(`a2`.`actionid`) AS `assists`
FROM `Player` AS `p`
LEFT JOIN `Actions` AS `a1`
ON `a1`.`id` = `p`.`id`
LEFT JOIN `Actions` AS `a2`
ON `a2`.`id` = `p`.`id`
WHERE `a1`.`type` = 'goal'
AND `a2`.`type` = 'assist'
GROUP BY
`a1`.`userId`,
`a2`.`userId`
LIMIT 0 , 30
I noticed in your query that you're joining your actions
table on a condition which references a table aliased as u
of which you don't have any table assigned. So, I think your query is probably throwing a MySQL error. Also, in your join conditions you are referencing the Actions
table's id
field, which I would expect to be, under normal convention, a primary auto-increment key. You may be using it as the player id, I'm unsure, but to be more verbose I changed it to read player_id
so you and other would know exactly what was going on in the query below. Under the assumption that you edited your query to be "easier to read" in the SO editor and didn't test it, I tweaked it to what I thought would be more accurate.
When joining tables and running a COUNT
on the select, you can only count the total number of rows returned. You can't COUNT
based on the number of rows returned for a single table in the JOIN. If you absolutely must use COUNT
, you have to run more than 1 query (1 for each COUNT
you need to run) or use sub-queries that run the COUNT
for the particular condition you're looking for.
This query is possible to run as a single query, but COUNT
is not the solution. You use a combination of CASE
and SUM
. We run a CASE..WHEN
clause that tests each row to see if the action that has been joined is a goal or an assist. If it is a goal, we give the goals
column a value of 1
, and if it's an assist we give the assists
column a value of 1. Then we run an aggregate function (SUM
) to add up all the 1s for goals
and assists
, and GROUP BY
the player id. This gives you a single row for each player with the total # of goals and assists they earned even for the players that earned 0.
SELECT
p.payername,
SUM(CASE a.type WHEN 'goal' THEN 1 ELSE 0 END) goals,
SUM(CASE a.type WHEN 'assist' THEN 1 ELSE 0 END) assists
FROM Player p
LEFT JOIN Actions a ON a.player_id = p.id
GROUP BY p.id
LIMIT 0, 30
I hope that helps you out and makes sense to you. You can check out the documentation for CASE
to get some more insight if you're still confused.
精彩评论