Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

Sự cố khi nhận được số lượng chính xác khi tham gia

Tôi nghĩ rằng cách tiếp cận đơn giản nhất đối với những gì bạn đang cố gắng thực hiện là chỉ sử dụng các truy vấn phụ có tương quan.

Vì vậy, ví dụ đầu tiên ngay bên dưới trả về kết quả bạn đang tìm kiếm . Bạn có thể dễ dàng sửa đổi nó để loại trừ các hàng không có bàn thắng và đường kiến ​​tạo.

Nó sử dụng giá trị team_id trong mỗi truy vấn con, nhưng bạn có thể cung cấp giá trị đó với một biến hoặc tham số, như được hiển thị, để bạn chỉ cần chỉ định giá trị một lần:

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

Đối với đội 1:

+----+-----------+-------+---------+
| id | last_name | Goals | Assists |
+----+-----------+-------+---------+
|  1 | Gretzky   |     2 |       1 |
|  2 | Lemieux   |     0 |       0 |
|  3 | Messier   |     1 |       1 |
+----+-----------+-------+---------+

Đối với đội 2:

+----+-----------+-------+---------+
| id | last_name | Goals | Assists |
+----+-----------+-------+---------+
|  1 | Gretzky   |     0 |       0 |
|  2 | Lemieux   |     1 |       0 |
|  3 | Messier   |     0 |       0 |
+----+-----------+-------+---------+

Đối với đội 3:

+----+-----------+-------+---------+
| id | last_name | Goals | Assists |
+----+-----------+-------+---------+
|  1 | Gretzky   |     0 |       1 |
|  2 | Lemieux   |     0 |       0 |
|  3 | Messier   |     1 |       0 |
+----+-----------+-------+---------+

Phần kết

Từ góc độ cố gắng thực hiện điều này với ít truy vấn con hơn và / hoặc với các truy vấn tổng hợp, bạn sẽ gặp một số vấn đề với lần thử đầu tiên của mình.

Một vấn đề là truy vấn của bạn có thể sẽ không hoạt động chính xác nếu bạn không bao gồm tất cả các trường trong nhóm group by mặc dù MySQL sẽ không hiểu bạn về điều đó như (hầu hết?) các cơ sở dữ liệu khác sẽ làm như vậy.

Ngoài ra, bởi vì các thành tích trong cả bảng kiến ​​tạo và cầu thủ của bạn chỉ liên quan gián tiếp đến các đội thông qua bảng bàn thắng, nên khá khó để có được một bản tổng hợp độc lập về cả mục tiêu và hỗ trợ chỉ với một truy vấn.

Như một minh họa cho các loại, các câu trả lời ban đầu khác cho vấn đề này, bao gồm cả bức ảnh chụp nhanh đầu tiên của tôi về nó, có một số vấn đề:

  • Nếu một cầu thủ đã kiến ​​tạo cho một đội, nhưng không có bất kỳ bàn thắng nào cho đội đó, thì các truy vấn sẽ không thể trả về bất kỳ kết quả nào cho sự kết hợp giữa cầu thủ và đội đó. Kết quả không đầy đủ.

  • Nếu một cầu thủ đã ghi bàn cho một đội, nhưng không có đường kiến ​​tạo nào cho đội đó, các truy vấn sẽ vẫn trả về một số dương cho các đường kiến ​​tạo khi đáng lẽ chúng phải trả về 0. Kết quả thực sự sai, không chỉ là không đầy đủ .

Ngay bên dưới là một giải pháp đúng hơn một chút, nhưng vẫn chưa hoàn thiện. Nó chỉ ra một cách chính xác nếu một cầu thủ không có hỗ trợ, mặc dù bằng cách trả về null thay vì 0, điều này thật đáng tiếc.

Nhưng đó vẫn là một giải pháp một phần vì nếu một cầu thủ không có bất kỳ bàn thắng nào cho một đội, bạn vẫn sẽ không thấy bất kỳ đường kiến ​​tạo nào cho sự kết hợp giữa cầu thủ và đội đó.

Điều này sử dụng một truy vấn con như một bảng ảo tổng hợp các hỗ trợ cho mỗi cầu thủ và đội và kết nối bên ngoài bên trái với truy vấn phụ là điều khiến nó trả về một kết quả nếu có bàn thắng, nhưng không có hỗ trợ.

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

Truy vấn đó trả về các kết quả sau:

+----+-----------+-------+---------+
| id | last_name | Goals | Assists |
+----+-----------+-------+---------+
|  1 | Gretzky   |     2 |       1 |
|  3 | Messier   |     1 |       1 |
+----+-----------+-------+---------+

Chạy phần này cho đội 2 và bạn sẽ nhận được các kết quả tiếp theo, cho thấy rằng Lemieux không có bất kỳ đường kiến ​​tạo nào cho đội 2, nhưng không trả về kết quả nào cho hai người chơi còn lại, những người không có đường kiến ​​tạo và không có bàn thắng nào cho đội 2:

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

Cuối cùng, hãy chạy nó cho đội 3 và bạn nhận được những kết quả tiếp theo, cho thấy rằng Messier không có bất kỳ pha kiến ​​tạo nào cho đội 3. Nhưng Gretzky đã mất tích, mặc dù anh ấy có một pha kiến ​​tạo cho đội 3, vì anh ấy không có. bất kỳ mục tiêu nào cho đội 3. Vì vậy, giải pháp không hoàn thành:

+----+-----------+-------+---------+
| 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. MYSQL - Ghép hai bảng

  2. Phương pháp băm mật khẩu Mysql cũ và mới

  3. Không thể chuyển tham số bằng tham chiếu trong MySQLi

  4. Nhiều CHÈN VÀO MySQL từ mảng $ _POST

  5. Plugin xác thực 'caching_sha2_password' không được hỗ trợ