Mysql
 sql >> база данни >  >> RDS >> Mysql

Проблем с правилното преброяване с присъединяване

Мисля, че най-простият подход към това, което се опитвате да направите, е просто да използвате корелирани подзаявки.

И така, първият пример точно по-долу връща резултатите, които търсите . Можете лесно да го промените, за да изключите редовете с нула голове и асистенции.

Той използва стойността team_id във всяка подзаявка, но можете да я предоставите с променлива или параметър, както е показано, така че да трябва да посочите стойността само веднъж:

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 |
+----+-----------+-------+---------+

Епилог

От гледна точка на опита да направите това с по-малко подзаявки и/или с обобщени заявки, имате няколко проблема, които възникват при първия ви опит.

Един проблем е, че вашата заявка вероятно няма да работи правилно, ако не включите всички полета във вашата group by клауза, въпреки че MySQL няма да ви укори за това, както (повечето?) други бази данни.

Освен това, тъй като записите във вашите таблици с асистенции и играчи са само косвено свързани с отборите чрез таблицата с голове, е доста трудно да получите независим сбор за двата голове и асистенции само с една заявка.

Като своеобразна илюстрация, други ранни отговори на това, включително първият ми бърз опит за това, имаха няколко проблема:

  • Ако даден играч е имал асистенции за даден отбор, но не е имал голове за този отбор, заявките не могат да върнат никакви резултати за този играч и комбинацията от отбори. Резултатите бяха непълни.

  • Ако играч е имал голове за даден отбор, но не е имал асистенции за този отбор, заявките пак ще върнат положително число за асистенции, когато е трябвало да върнат нула. Резултатите всъщност бяха грешни, а не просто непълни .

Точно по-долу е малко по-правилно, но все още непълно решение. Правилно показва дали даден играч няма асистенции, макар и като връща нула вместо 0, което е жалко.

Но това все още е частично решение, защото ако даден играч няма никакви голове за даден отбор, пак няма да видите никакви асистенции за този играч и комбинация от отбор.

Това използва подзаявка като виртуална таблица, която обобщава асистенциите за играч и отбор, а лявото външно съединение към подзаявката е това, което я кара да връща резултат, ако има голове, но няма асистенции.

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:

+----+-----------+-------+---------+
| id | last_name | Goals | Assists |
+----+-----------+-------+---------+
|  2 | Lemieux   |     1 |    null |
+----+-----------+-------+---------+

И накрая, пуснете го за отбор 3 и ще получите тези следващи резултати, показващи, че Месие няма асистенции за отбор 3. Но Грецки липсва, въпреки че има асистенция за отбор 3, защото той няма всякакви цели за отбор 3. Така че решението не е пълно:

+----+-----------+-------+---------+
| id | last_name | Goals | Assists |
+----+-----------+-------+---------+
|  3 | Messier   |     1 |    null |
+----+-----------+-------+---------+



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как правилно да дезинфекцирам данните, получени от текстова област, когато ги извеждам обратно в текстовата област?

  2. Избиране на групи от последователни записи с общ атрибут?

  3. Изчислете дълбочината в модел родител-дете в MySQL

  4. Извличане на редове, чиято стойност е дадена, която се намира между два реда с дадено условие

  5. Мога ли да смесвам MySQL API в PHP?