09. august 2007 - 21:00Der 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.
Teknologi, AI og forretning er i centrum på Computerworlds Cloud og AI Festival i København d. 18. og 19. september. Se hele programmet for den store konference om strategisk brug af Cloud og AI på: www.cloud-festival.dk
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
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.
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.
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)
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.
Synes godt om
Ny brugerNybegynder
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.