Avatar billede AnyFellow Mester
09. august 2007 - 21:00 Der er 6 kommentarer og
1 løsning

Fejl i JOINS i forespørgsel

Jeg har 3 tabeller:

fl_brugere
fl_firmaoplysninger
fl_omr_ref

En bruger optræder én gang i fl_brugere.
En brugers oplysninger optræder én gang i fl_firmaoplysninger.
En bruger kan have mange poster i fl_omr_ref.

Jeg ønsker at hente nogle bestemte bruger, såfremt mine kriterier er opfyldt.

Min foreløbige forespørgsel ser sådan her ud:

SELECT fl_brugere.id AS id
FROM fl_brugere
LEFT JOIN fl_omr_ref ON fl_brugere.id = fl_omr_ref.firmaid
LEFT JOIN fl_firmaoplysninger ON fl_brugere.id = fl_firmaoplysninger.id
WHERE fl_brugere.betalt_dato > '$dags_dato'
AND fl_omr_ref.kategoriid    = '$kat_id'
ORDER BY $sortering

Det jeg ønsker er:
En bruger er oprettet i fl_brugere med et id (fl_brugere.id). Dette id er nøgle.
En brugers oplysninger er oprettet i fl_firmaoplysninger (fl_firmaoplysninger.id).
En brugers områder er oprettet i fl_omr_ref (fl_omr_ref.firmaid).

Jeg har f.eks. et firma der har 4 poster i fl_omr_ref.
Dette resulterer i at firmaet dukker op 4 gange i resultatet af min forespørgsel.

Hvad gør jeg forkert?
Avatar billede AnyFellow Mester
10. august 2007 - 20:29 #1
Slet ingen der kan hjælpe?

Pointtal hævet.
Avatar billede kjulius Novice
10. august 2007 - 23:33 #2
Det er meget nemt at undgå, du tilføjer bare et DISTINCT til din forespørgsel, så får du kun værdier som er forskellige:

SELECT DISTINCT fl_brugere.id AS id
FROM fl_brugere
LEFT JOIN fl_omr_ref ON fl_brugere.id = fl_omr_ref.firmaid
LEFT JOIN fl_firmaoplysninger ON fl_brugere.id = fl_firmaoplysninger.id
WHERE fl_brugere.betalt_dato > '$dags_dato'
AND fl_omr_ref.kategoriid    = '$kat_id'
ORDER BY $sortering
Avatar billede kjulius Novice
10. august 2007 - 23:40 #3
Forresten, i din SELECT laver du et alias (eller rename om du vil) af feltet id fra tabellen fl_brugere til id. Det er lidt omsonst (id til id). Det kan somme tider være en god idé at lave en rename, især hvis et felt optræder med samme navn i flere tabeller. F.eks:

SELECT fl_brugere.id AS flb_id, fl_omr_ref.id AS flo_id

men det er kun relevant fordi begge felter medtages i selecten og/eller fordi feltnavnet skal gøres mere sigende.
Avatar billede kjulius Novice
10. august 2007 - 23:49 #4
Der er endnu et paradox (synes jeg :-)), nemlig at du overhovedet laver det som en left (outer) join. Med mindre du også tillader NULL som en tilladt værdi i din WHERE sætning (ved test på felter fra tabeller, hvor en OUTER JOIN er brugt), vil det virke som en INNER join.

Hvis du ønsker kun at få præsenteret de brugere, som har tilknyttet et firma, bør du bruge INNER JOIN i stedet. Det er mere logisk og nemmere at overskue hvis du på et senere tidspunkt kigger på koden igen.
Avatar billede kjulius Novice
10. august 2007 - 23:59 #5
"nemlig at du overhovedet laver det som en left (outer) join"

Hvis du er i tvivl, så er det tabellen "fl_omr_ref" jeg taler om. :-)
Du tester på feltet kategoriid uden at tillade null:

AND (fl_omr_ref.kategoriid IS NULL OR fl_omr_ref.kategoriid    = '$kat_id')
Avatar billede AnyFellow Mester
11. august 2007 - 10:07 #6
Det overrasker mig ikke at jeg ikke bruger joins optimalt.

Jeg er også meget i tvivl om hvorvidt der er hurtigst at lave den forespørgsel jeg gør, eller om det vil være hurtigere (og mindre belastende for serveren), at opdele min forespørgsel i 3 forespørgsler?

DISTINCT løste mit problem. Læg et svar og der er velfortjente point på vej :O)
Avatar billede kjulius Novice
11. august 2007 - 10:57 #7
Det er som regel ikke optimalt at udføre flere forespørgsler end nødvendigt. Hvis det er muligt at hive alle de nødvendige informationer ud i ét hug, er det som regel mere effektivt.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Computerworld tilbyder specialiserede kurser i database-management

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester