Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

Kesulitan mendapatkan hitungan yang benar dengan bergabung

Saya pikir pendekatan paling mudah untuk apa yang Anda coba lakukan adalah dengan hanya menggunakan subkueri yang berkorelasi.

Jadi, contoh pertama tepat di bawah mengembalikan hasil yang Anda cari . Anda dapat dengan mudah memodifikasinya untuk mengecualikan baris tanpa gol dan assist.

Ini menggunakan nilai team_id di setiap subkueri, tetapi Anda dapat menyediakannya dengan variabel atau parameter, seperti yang ditunjukkan, sehingga Anda hanya perlu menentukan nilainya sekali:

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

Untuk tim 1:

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

Untuk tim 2:

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

Untuk tim 3:

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

Epilog

Dari perspektif mencoba melakukan ini dengan lebih sedikit subkueri dan/atau dengan kueri agregat, Anda memiliki beberapa masalah yang terjadi dengan upaya pertama Anda.

Satu masalah adalah bahwa kueri Anda mungkin tidak akan berfungsi dengan benar jika Anda tidak menyertakan semua bidang dalam group by Anda klausa meskipun MySQL tidak akan mengeluh pada Anda tentang itu seperti (kebanyakan?) database lain akan.

Selain itu, karena catatan di tabel assist dan pemain Anda hanya terkait secara tidak langsung dengan tim melalui tabel gol, cukup sulit untuk mendapatkan rollup independen pada kedua gol dan assist hanya dengan satu kueri.

Sebagai ilustrasi, jawaban awal lainnya untuk ini, termasuk tembakan cepat pertama saya, memiliki beberapa masalah:

  • Jika seorang pemain memiliki assist untuk sebuah tim, tetapi tidak memiliki gol untuk tim tersebut, kueri tidak dapat mengembalikan hasil apa pun untuk kombinasi pemain dan tim tersebut. Hasilnya tidak lengkap.

  • Jika seorang pemain mencetak gol untuk sebuah tim, tetapi tidak memiliki assist untuk tim tersebut, kueri akan tetap menghasilkan angka positif untuk assist ketika mereka seharusnya mengembalikan nol. Hasilnya sebenarnya salah, bukan hanya tidak lengkap .

Tepat di bawah ini adalah solusi yang sedikit lebih benar, tetapi masih belum lengkap. Ini menunjukkan dengan benar jika seorang pemain tidak memiliki assist, meskipun dengan mengembalikan null alih-alih 0 yang sangat disayangkan.

Namun ini masih merupakan solusi parsial karena jika seorang pemain tidak mencetak gol untuk tim, Anda tetap tidak akan melihat assist untuk kombinasi pemain dan tim tersebut.

Ini menggunakan subquery sebagai tabel virtual yang mengumpulkan assist per pemain dan tim, dan bagian luar kiri yang bergabung dengan subquery inilah yang membuatnya mengembalikan hasil jika ada gol, tapi tidak ada assist.

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

Kueri itu mengembalikan hasil ini:

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

Jalankan ini untuk tim 2, dan Anda mendapatkan hasil berikutnya, yang menunjukkan bahwa Lemieux tidak memiliki assist untuk tim 2, tetapi tidak memberikan hasil sama sekali untuk dua pemain lainnya, yang tidak memiliki assist dan tidak ada gol untuk tim 2:

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

Akhirnya, jalankan untuk tim 3, dan Anda mendapatkan hasil berikut ini, yang menunjukkan bahwa Messier tidak memiliki assist untuk tim 3. Tapi Gretzky hilang, meskipun dia memiliki assist untuk tim 3, karena dia tidak memilikinya. tujuan any untuk tim 3. Jadi solusinya belum selesai:

+----+-----------+-------+---------+
| 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. Tidak dapat menetapkan indeks FULLTEXT di meja saya

  2. Membuat pencarian langsung di database dengan CodeIgniter, php5 dan MySQL

  3. Memindahkan dan Mencadangkan Database MySQL Besar

  4. acak 2 catatan sesuai dengan posisi dan urutan berdasarkan posisi

  5. Mencari susunan MySQL yang tidak peka huruf besar-kecil di mana a !=