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