あなたがやろうとしていることへの最も簡単なアプローチは、相関するサブクエリを使用することだと思います。
したがって、すぐ下の最初の例は、探している結果を返します 。目標とアシストがゼロの行を除外するように簡単に変更できます。
各サブクエリでteam_id値を使用しますが、示されているように変数またはパラメーターを指定して指定できるため、値を1回指定するだけで済みます。
set @team_id := 2;
select
p.id as player_id
, p.last_name
, (
select count(*)
from goals
where player_id = p.id
and team_id = @team_id
) as goals
, (
select count(*)
from assists
inner join goals on assists.goal_id = goals.id
where assists.player_id = p.id
and goals.team_id = @team_id
) as assists
from players p
チーム1の場合:
+----+-----------+-------+---------+
| id | last_name | Goals | Assists |
+----+-----------+-------+---------+
| 1 | Gretzky | 2 | 1 |
| 2 | Lemieux | 0 | 0 |
| 3 | Messier | 1 | 1 |
+----+-----------+-------+---------+
チーム2の場合:
+----+-----------+-------+---------+
| id | last_name | Goals | Assists |
+----+-----------+-------+---------+
| 1 | Gretzky | 0 | 0 |
| 2 | Lemieux | 1 | 0 |
| 3 | Messier | 0 | 0 |
+----+-----------+-------+---------+
チーム3の場合:
+----+-----------+-------+---------+
| id | last_name | Goals | Assists |
+----+-----------+-------+---------+
| 1 | Gretzky | 0 | 1 |
| 2 | Lemieux | 0 | 0 |
| 3 | Messier | 1 | 0 |
+----+-----------+-------+---------+
エピローグ
より少ないサブクエリや集計クエリでこれを実行しようとすると、最初の試行でいくつかの問題が発生します。
1つの問題は、group by
にすべてのフィールドを含めないと、クエリが正しく機能しない可能性があることです。 MySQLは(ほとんど?)他のデータベースのようにそれについてあなたに不満を抱くことはありませんが、節。
また、アシストテーブルとプレーヤーテーブルの両方のレコードは、ゴールテーブルを介してチームに間接的にのみ関連しているため、両方のゴールで独立したロールアップを取得し、1つのクエリでアシストするのはかなり困難です。
ある種の例として、これに対する他の初期の回答には、最初のクイックショットを含め、いくつかの問題がありました。
-
プレーヤーがチームのアシストを持っていたが、そのチームの目標がなかった場合、クエリはそのプレーヤーとチームの組み合わせの結果を返すことができませんでした。結果は不完全でした。
-
プレーヤーがチームの目標を持っていても、そのチームのアシストがなかった場合でも、ゼロを返す必要があるときに、クエリはアシストに対して正の数を返します。 結果は、不完全なだけでなく、実際には間違っていました。 。
すぐ下はもう少し正しいですが、それでも不完全な解決策です。残念ながら、0ではなくnullを返すことで、プレーヤーにアシストがないかどうかが正しく示されます。
ただし、プレーヤーにチームの目標がない場合でも、そのプレーヤーとチームの組み合わせに対するアシストは表示されないため、これはまだ部分的な解決策です。
これは、プレーヤーとチームごとにアシストを集約する仮想テーブルとしてサブクエリを使用します。サブクエリへの左側の外部結合により、目標はあるがアシストがない場合に結果が返されます。
select
p.id as player_id
, p.last_name
, count(g.game_id) as goals
, a.assists
from players p
inner join goals g on p.id = g.player_id
left join (
select
assists.player_id
, goals.team_id
, count(assists.id) as assists
from assists
inner join goals on assists.goal_id = goals.id
group by player_id, team_id, assists.id
) a
on g.player_id = a.player_id and g.team_id = a.team_id
where g.team_id = 1
group by player_id, last_name, g.team_id
そのクエリはこれらの結果を返します:
+----+-----------+-------+---------+
| id | last_name | Goals | Assists |
+----+-----------+-------+---------+
| 1 | Gretzky | 2 | 1 |
| 3 | Messier | 1 | 1 |
+----+-----------+-------+---------+
チーム2でこれを実行すると、次の結果が得られます。これは、Lemieuxがチーム2のアシストを持っていないことを示していますが、チーム2のアシストもゴールもない他の2人のプレーヤーにはまったく結果を返していません。
+----+-----------+-------+---------+
| id | last_name | Goals | Assists |
+----+-----------+-------+---------+
| 2 | Lemieux | 1 | null |
+----+-----------+-------+---------+
最後に、チーム3で実行すると、次の結果が得られます。これは、メシエがチーム3のアシストを持っていないことを示しています。しかし、グレツキーはチーム3のアシストを持っていても、持っていないため、行方不明になっています。 目標 チーム3の場合。したがって、ソリューションは完全ではありません。
+----+-----------+-------+---------+
| id | last_name | Goals | Assists |
+----+-----------+-------+---------+
| 3 | Messier | 1 | null |
+----+-----------+-------+---------+