sql >> Database teknologi >  >> RDS >> Mysql

MySql:Multiple Left Join giver forkert output

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



  1. Der er symboler som  og så videre i databasen, hvad skal man gøre?

  2. Hvordan hacker man MySQL GROUP_CONCAT for at hente et begrænset antal rækker?

  3. travis mysql database oprette bruger fejl

  4. Hvordan skriver man en MYSQL-forespørgsel, der returnerer børn indlejret under forældre?