Du skal udjævne resultaterne af din forespørgsel, for at opnå en korrekt optælling.
Du sagde, at du har en-til-mange relationer fra din filtabel til andre tabeller
Hvis SQL kun har et nøgleord LOOKUP
i stedet for at proppe alt i JOIN
søgeord, skal det være let at udlede, om relationen mellem tabel A og tabel B er en-til-en ved hjælp af JOIN
betyder automatisk en-til-mange. jeg afviger. Anyway, jeg burde allerede have udledt, at dine filer er en-til-mange mod dm_data; og også, filerne mod kc_data er også en-til-mange. LEFT JOIN
er endnu et hint om, at forholdet mellem første tabel og anden tabel er en-til-mange; dette er dog ikke endegyldigt, nogle kodere skriver bare alt med LEFT JOIN
. Der er ikke noget galt med din LEFT JOIN i din forespørgsel, men hvis der er flere en-til-mange tabeller i din forespørgsel, vil det helt sikkert mislykkes, din forespørgsel vil producere gentagne rækker mod andre rækker.
fra filer venstre join dm_data ON dm_data.id =files.id left join kc_data ON kc_data.id =files.id
Så med denne viden, at du angiver, at filer er en-til-mange mod dm_data, og det er en-til-mange også mod kc_data. Vi kan konkludere, at der er noget galt med at sammenkæde disse joinforbindelser og gruppere dem på én monolitisk forespørgsel.
Et eksempel, hvis du har tre tabeller, nemlig app(filer), ios_app(dm_data), android_app(kc_data), og dette er dataene for f.eks. ios:
test=# vælg * fra ios_app rækkefølge efter app_code, date_released; ios_app_id | app_kode | udgivelsesdato | pris ------------+----------+---------------+-------- 1 | AB | 2010-01-01 | 1.0000 3 | AB | 03-01-2010 | 3.0000 4 | AB | 2010-01-04 | 4.0000 2 | TR | 2010-01-02 | 2.0000 5 | TR | 2010-01-05 | 5.0000(5 rækker)
Og dette er dataene til din Android:
test=# vælg * fra android_app ordre efter app_code, date_released;.android_app_id | app_kode | udgivelsesdato | pris --------------+-----------+------------------ ---- 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 rækker)
Hvis du kun bruger denne forespørgsel:
vælg x.app_code, count(i.date_released) as ios_release_count, count(a.date_released) as android_release_countfrom app xleft join ios_app i on i.app_code =x.app_codeleft join android_app a on a.app_code =x .app_codegroup by x.app_codeorder by x.app_code
Outputtet vil i stedet være forkert:
app_kode | ios_release_count | android_release_count ----------+------------------------+------------------------ ----- AB | 6 | 6 MK | 0 | 13:00 | 0 | 0 TR | 8 | 8(4 rækker)
Du kan tænke på kædede joinforbindelser som kartesiske produkter, så hvis du har 3 rækker på det første bord og har 2 rækker på det andet bord, vil outputtet være 6
Her er visualiseringen, se at der er 2 gentagne android AB for hver ios AB. Der er 3 ios AB, så hvad ville antallet være, når du laver COUNT(ios_app.date_released)? Det bliver til 6; det samme med COUNT(android_app.date_released)
, vil dette også være 6. Ligeledes er der 4 gentagne Android TR for hver ios TR, der er 2 TR i iOS, så det ville give os et tal på 8.
.app_code | ios_release_date | android_release_date ----------+------------------------+------------------------ --- AB | 2010-01-01 | 2010-01-06 AB | 2010-01-01 | 2010-01-07 AB | 03-01-2010 | 2010-01-06 AB | 03-01-2010 | 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 rækker)
Så det, du skal gøre, er at udjævne hvert resultat, før du forbinder dem med andre tabeller og forespørgsler.
Hvis din database er i stand til CTE, skal du bruge det. Det er meget pænt og meget selvdokumenterende:
med ios_app_release_count_list som( vælg app_kode, count(date_released) som ios_release_count fra ios_app group by app_code),android_release_count_list as( select app_code, count(date_released) as android_release_count fra android_release_count fra android_app_code, select xalesce_ (i.ios_release_count,0) as ios_release_count, coalesce(a.android_release_count,0) as android_release_countfrom app xleft join ios_app_release_count_list i på i.app_code =x.app_codeleft join android_release_count_coder a.
Hvorimod hvis din database ikke har nogen CTE-kapacitet endnu, som MySQL, bør du gøre dette i stedet:
vælg x.app_code, coalesce(i.ios_release_count,0) som ios_release_count, coalesce(a.android_release_count,0) som android_release_countfrom app xleft join( vælg app_code, count(date_release) som ios_release_app group fra ios_release_app group ) i på i.app_code =x.app_codeleft join( vælg app_code, count(date_released) som android_release_count fra android_app group by app_code ) a på a.app_code =x.app_codeorder by x.app_code
Denne forespørgsel og forespørgslen i CTE-stil viser det korrekte output:
app_kode | ios_release_count | android_release_count ----------+------------------------+------------------------ ----- AB | 3 | 2 MK | 0 | 13:00 | 0 | 0 TR | 2 | 4(4 rækker)
Livetest
Forkert forespørgsel:http://www.sqlfiddle.com/#!2/9774a/ 2
Korrekt forespørgsel:http://www.sqlfiddle.com/#!2/9774a/ 1