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

MySql:Beberapa Gabung Kiri memberikan hasil yang salah

Anda perlu meratakan hasil permintaan Anda, untuk mendapatkan hitungan yang tepat.

Anda mengatakan bahwa Anda memiliki hubungan satu-ke-banyak dari tabel file Anda ke tabel lain

Jika SQL hanya memiliki kata kunci LOOKUP alih-alih menjejalkan semuanya dalam JOIN kata kunci, akan mudah untuk menyimpulkan jika hubungan antara tabel A dan tabel B adalah satu-ke-satu, menggunakan JOIN otomatis akan berkonotasi satu-ke-banyak. saya ngelantur. Bagaimanapun, saya seharusnya sudah menyimpulkan bahwa file Anda adalah satu-ke-banyak terhadap dm_data; dan juga, file terhadap kc_data juga satu-ke-banyak. LEFT JOIN adalah petunjuk lain bahwa hubungan antara tabel pertama dan tabel kedua adalah satu-ke-banyak; ini tidak pasti, beberapa pembuat kode hanya menulis semuanya dengan LEFT JOIN . Tidak ada yang salah dengan LEFT JOIN Anda dalam kueri Anda, tetapi jika ada beberapa tabel satu-ke-banyak dalam kueri Anda, itu pasti akan gagal, kueri Anda akan menghasilkan baris berulang terhadap baris lainnya.

from
    files
        left join
    dm_data ON dm_data.id = files.id
        left join
    kc_data ON kc_data.id = files.id

Jadi dengan pengetahuan ini bahwa Anda menunjukkan bahwa file adalah satu-ke-banyak terhadap dm_data, dan ini adalah satu-ke-banyak juga terhadap kc_data. Kita dapat menyimpulkan bahwa ada yang salah dengan merangkai gabungan tersebut dan mengelompokkannya pada satu kueri monolitik.

Contoh jika Anda memiliki tiga tabel yaitu app(files), ios_app(dm_data), android_app(kc_data), dan ini adalah datanya misalnya untuk ios:

test=# select * from ios_app order by app_code, date_released;
 ios_app_id | app_code | date_released | price  
------------+----------+---------------+--------
          1 | AB       | 2010-01-01    | 1.0000
          3 | AB       | 2010-01-03    | 3.0000
          4 | AB       | 2010-01-04    | 4.0000
          2 | TR       | 2010-01-02    | 2.0000
          5 | TR       | 2010-01-05    | 5.0000
(5 rows)

Dan ini adalah data untuk android Anda:

test=# select * from android_app order by app_code, date_released;
.android_app_id | app_code | date_released |  price  
----------------+----------+---------------+---------
              1 | AB       | 2010-01-06    |  6.0000
              2 | AB       | 2010-01-07    |  7.0000
              7 | MK       | 2010-01-07    |  7.0000
              3 | TR       | 2010-01-08    |  8.0000
              4 | TR       | 2010-01-09    |  9.0000
              5 | TR       | 2010-01-10    | 10.0000
              6 | TR       | 2010-01-11    | 11.0000
(7 rows)    

Jika Anda hanya menggunakan kueri ini:

select x.app_code, 
    count(i.date_released) as ios_release_count, 
    count(a.date_released) as android_release_count
from app x
left join ios_app i on i.app_code = x.app_code
left join android_app a on a.app_code = x.app_code
group by x.app_code
order by x.app_code

Outputnya akan salah sebagai gantinya:

 app_code | ios_release_count | android_release_count 
----------+-------------------+-----------------------
 AB       |                 6 |                     6
 MK       |                 0 |                     1
 PM       |                 0 |                     0
 TR       |                 8 |                     8
(4 rows)

Anda dapat menganggap gabungan berantai sebagai produk kartesius, jadi jika Anda memiliki 3 baris di tabel pertama, dan memiliki 2 baris di tabel kedua, hasilnya adalah 6

Berikut visualisasinya, terlihat ada 2 pengulangan android AB untuk setiap ios AB. Ada 3 ios AB, jadi berapa hitungannya saat Anda melakukan COUNT(ios_app.date_released)? Itu akan menjadi 6; sama dengan COUNT(android_app.date_released) , ini juga akan menjadi 6. Demikian juga ada 4 TR android yang berulang untuk setiap TR ios, ada 2 TR di ios, sehingga akan memberi kita hitungan 8.

.app_code | ios_release_date | android_release_date 
----------+------------------+----------------------
 AB       | 2010-01-01       | 2010-01-06
 AB       | 2010-01-01       | 2010-01-07
 AB       | 2010-01-03       | 2010-01-06
 AB       | 2010-01-03       | 2010-01-07
 AB       | 2010-01-04       | 2010-01-06
 AB       | 2010-01-04       | 2010-01-07
 MK       |                  | 2010-01-07
 PM       |                  | 
 TR       | 2010-01-02       | 2010-01-08
 TR       | 2010-01-02       | 2010-01-09
 TR       | 2010-01-02       | 2010-01-10
 TR       | 2010-01-02       | 2010-01-11
 TR       | 2010-01-05       | 2010-01-08
 TR       | 2010-01-05       | 2010-01-09
 TR       | 2010-01-05       | 2010-01-10
 TR       | 2010-01-05       | 2010-01-11
(16 rows)

Jadi yang harus Anda lakukan adalah meratakan setiap hasil sebelum Anda menggabungkannya ke tabel dan kueri lainnya.

Jika database Anda mampu CTE, silakan gunakan begitu. Ini sangat rapi dan sangat mendokumentasikan diri sendiri:

with ios_app_release_count_list as
(
 select app_code, count(date_released) as ios_release_count
 from ios_app
 group by app_code
)
,android_release_count_list as
(
 select app_code, count(date_released) as android_release_count 
 from android_app 
 group by app_code  
)
select
 x.app_code, 
 coalesce(i.ios_release_count,0) as ios_release_count, 
 coalesce(a.android_release_count,0) as android_release_count
from app x
left join ios_app_release_count_list i on i.app_code = x.app_code
left join android_release_count_list a on a.app_code = x.app_code
order by x.app_code;

Sedangkan jika database Anda belum memiliki kemampuan CTE, seperti MySQL, Anda harus melakukan ini sebagai gantinya:

select x.app_code, 
 coalesce(i.ios_release_count,0) as ios_release_count, 
 coalesce(a.android_release_count,0) as android_release_count
from app x
left join
(
 select app_code, count(date_released) as ios_release_count
 from ios_app
 group by app_code
) i on i.app_code = x.app_code
left join
(
 select app_code, count(date_released) as android_release_count 
 from android_app 
 group by app_code   
) a on a.app_code = x.app_code
order by x.app_code

Kueri itu dan kueri gaya CTE akan menampilkan keluaran yang benar:

 app_code | ios_release_count | android_release_count 
----------+-------------------+-----------------------
 AB       |                 3 |                     2
 MK       |                 0 |                     1
 PM       |                 0 |                     0
 TR       |                 2 |                     4
(4 rows)

Uji langsung

Permintaan salah:http://www.sqlfiddle.com/#!2/9774a/ 2

Permintaan yang benar:http://www.sqlfiddle.com/#!2/9774a/ 1



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Bagaimana Cara Memanggil Kode Java dari MySQL?

  2. Django menghubungkan masalah mysql, NameError:nama '_mysql' tidak ditentukan

  3. Untuk apa driver jdbc org.gjt.mm.mysql.Driver?

  4. Nilai benih MySQL RAND() hampir berulang

  5. Tidak dapat menginstal permata mysql di Mac OS X