26. september 2002 - 20:41Der er
17 kommentarer og 2 løsninger
DISTINCT med mer end én kolonne...
Jeg er igang med et statistiksystem i PHP, hvor jeg har en MySQL tabel med alle mine statistikdata i. Der kommer så en ny række for hver sidevisning, indeholdende IP, hostname osv. Jeg er så igang med at lave et system som kan fremvise statistikken, hvor jeg er nået til hvor man har valgt en måned og det så er meningen at man skal kunne se alle dagene for måneden, med navne på dagene, hvor weekenddagende skal være fremhævede. Det går da også fint nok, hvor jeg bruger en DISTINCT query til at finde ud af hvor mange dage der er i måneden. Den ser så sådan ud:
SELECT DISTINCT dag_maaned FROM statistik WHERE maaned='$maaned' AND aar='$aar' ORDER BY dag_maaned
Jeg skal jo så også kunne få fat i dagens navn og for ikke at skulle lave endnu en query, da det i forvejen går rimelig langsomt, så ville jeg gerne have hvis jeg kunne få "dag_uge" ind.
Jeg har så prøvet at lave denne:
SELECT DISTINCT dag_uge, dag_maaned FROM statistik WHERE maaned='$maaned' AND aar='$aar' ORDER BY dag_maaned
Det hele fungerer nu som det skal, men så er spørgsmålet så bare om det er korrekt at lave det på den måde? Hvordan foregår det i det hele taget? Umiddelbart ville jeg jo tro at den ville finde 7 forskellige "dag_uge" og så derved kun kunne fortsætte med at finde 7 "dag_maaned", eller har jeg misforstået noget?
Jeg ville i øvrigt meget gerne have et link til MySQL manualen hvor der står om DISTINCT, hvis nogen ville hjælpe mig med at findet frem til det. ;-)
Den moderne arbejdsplads er i stigende grad afhængig af mødelokaler til at fremme samarbejde, men dette skift medfører også stigende sikkerhedsudfordringer.
du har kun angivet at dag_uge er distinct, prøv med: SELECT DISTINCT dag_uge, DISTINCT dag_maaned FROM statistik WHERE maaned='$maaned' AND aar='$aar' ORDER BY dag_maaned
Det er jo kun dag_maaned som skal være DISTINCT og dag_uge er bare noget jeg vil kunne trække ud af databasen samtidig med DISTINCT. Jeg har også tænkt på GROUP BY, men hvordan fungerer det? Er der noget med at man ikke kan bruge ORDER BY dér?
Det hjælper mig ikke meget... Jeg har testet at GROUP BY også sorterer, da man kan sætte DESC bagved, så den vender det om. Men så er spørgsmålet bare om DISTINCT eller GROUP BY er bedst. F.eks. når jeg skal have fat i en hel del mere dato information, så er det vel muligt at det vil opstå problemer hvis jeg sætter alt sammen i en DISTINCT jo...
Det er korrekt som du har lavet det med "SELECT DISTINCT dag_uge, dag_maaned", idet DISTINCT simpelthen fungerer på den måde at det smider alle duplikater i resultatet fra dit SELECT statement væk.
Teknisk set laver MySQL altid en GROUP BY automatisk når du benytter SELECT DISTINCT, og en GROUP BY vil dermed give samme resultat som en SELECT DISTINCT.
Var svaret tydeligt nok? Konklussionen var, at det du har gjort er 100% korrekt! :-)
P.S: DISTINCT skal ALTID står umiddelbart efter SELECT, og skal ikke som disky antyder angives pr. kolonne.
Det jeg så ikke forstår er om den tager de to i nogen rækkefølge, eller rettere om det kan have nogen betydning hvilken rækkefølge de to står i? F.eks. hvis vi siger at der er 31 dage i den måned jeg har valgt, der er måske chance for at der er 4 af hver ugedag, men som DISTINCT´en siger, så må der kun være én "dag_uge". Derfor skulle man tro at den derved kun har 7 resultater at arbejde med. Derefter skulle man tro at den tjekker med "dag_maaned" og der vil så nok være 7 forskellige - altså alle dem som blev fundet ved "dag_uge". Er det korrekt forstået eller har jeg misforstået det helt?
Hvis vi så lige arbejder videre fra det her, så hvis jeg har 5 ting mere jeg skal have trukket ud af databasen, så burde det jo igen kunne sætte antallet af resultater meget ned... Så det lyder jo ret ulogisk.
Som du så siger, så er DISTINCT faktisk præcis det samme som GROUP BY og MySQL faktisk selv går hen og laver den om til GROUP BY, så kan jeg så bare ikke forstå hvorfor man så ikke bare altid benytter GROUP BY? Er det så rigtigt at GROUP BY erstatter ORDER BY så?
Jeg synes nu også det virkede lidt mærkeligt det som disky sagde, med at man skulle skrive "DISTINCT" foran hver.
Det kan godt være, at GROUP BY resulterer i en eller anden sortering, men hvis man tilføjer et ORDER BY til sidst, bestemmer ORDER BY sorteringen.
DISTINCT: SELECT x,y,z FROM tabel WHERE x<1000; SELECT DISTINCT x,y,z FROM tabel WHERE x<1000; Den ENESTE forskel imellem disse to selects er, at der ikke er nogle ens RESULTAT-rækker. En resultat-række er i dette tilfælde x,y,z. DISTINCT påvirker altså ikke logikken i søgningen, men sorterer bare nogle resultater fra.
DISTINCT laver ikke umiddelbart nogen rækkefølge, men sørge alene for at KOMBINATIONEN af de felter du angiver er entydig! Du kan sagtens tilføje en "ORDER BY dag_maaned, dag_uge" hvis du ønsker at få resultatet sorteret.
GROUP BY erstatter ikke ORDER BY, og de to ting har ikke noget med hinanden at gøre. Dog er kolonnerne angivet i GROUP BY og ORDER BY meget ofte identiske, idet man ofte ønske at sortere på samme felter som man grupperer på.
Grunden til at man normalt vælger at anvende GROUP BY, er dels at det er hurtigere at skrive, og dels at det ved de fleste databaser er mindre ressource tungt end GROUP BY, men ved MySQL er forskellen minimal da den p.t. behandler DISTINCT som GROUP BY, men det kan dog ændre sig i senere versioner!
Normalt bør du kun benytte GROUP BY, hvis du har brug for grupperingsfunktioner som MIN, MAX, AVG, SUM eller lign.
lasse_buck -> Jeg mener bare at have læst at man slet ikke kan bruge ORDER BY, når man allerede har en GROUP BY!? Ville jo også være lidt skørt hvis man ønskede GROUP BY på én kolonne, men ville sortere efter en anden.
Ang. dine eksempler med DISTINCT, så skriver du jo at der ikke vil komme nogle ens resultatrækker, men hvis vi nu siger at f.eks. "y" kun er med fordi man ønsker at kunne få fat i dataene. Hvorfor sørger DISTINCT så ikke også for at sortere duplicater væk dér?
flse -> Nu forstår jeg ikke meget af det her mere, for f.eks. hvis den nu har sorteret alle duplikater fra ved dag_maaned, så har den måske 31 rækker tilbage. Derefter skulle man jo tro at den også ville tjekke for duplicater under dag_uge, da det jo egentlig står som DISTINCT, derfor kunne det jo godt tænkes at det kun ville blive 7 resultater (Én for hver ugedag!) når begge var udført.
Ang. ORDER BY, så må det bare være noget jeg har læst af én som ikke har kendt særlig meget til det, men det var bare her på eksperten.dk
"... dels at det ved de fleste databaser er mindre ressource tungt end GROUP BY", mener du ikke DISTINCT i steden for GROUP BY?
Jeg har ikke brug for nogle af de nævnte funktioner, men jeg synes at GROUP BY virker meget mere logisk, da man derved slipper for at få lavet DISTINCT på de andre kolonner, som man egentlig kun ønsker at trække ud af databasen i samme query.
Jeg bliver mere og mere forvirret som tiden går. ;(
SELECT DISTINCT behandler ALLE felter samtidig, så den ikke sortere duplikater fra ved dag_maaned, men ved kombinationen af dag_maaned og dag_uge. Altså at kolonnerne IKKE behandles individuelt men som et hele!
Og nej, GROUP BY vil normalt kræve flere ressourcer end DISTINCT.
Problemet med både DISTINCT og GROUP BY er at du ikke kan trække flere kolonner ud i samme query, end netop dem du ønsker skal være entydige! Problemet er jo at MySQL sorterer duplikaterne fra. Hvis du vil have f.eks. "dato" med også, så ville MySQL jo ikke vide hvilken af de frasorterede rækker den skal tage "dato" fra, da feltet ikke er en del af DISTINCT/GROUP BY, og dermed ikke entydigt.
Hvis du benytter GROUP BY har du dog muligheden for at lave:
SELECT dag_uge, dag_maaned, MAX(dato) FROM statistik WHERE maaned='$maaned' AND aar='$aar' GROUP BY dag_uge, dag_maaned ORDER BY dag_maaned
Ved GROUP BY kan du nemlig KUN angive kolonner i SELECT som også er i GROUP BY linien, medmindre du benytter grupperingsfunktioner på de øvrige felter, som f.eks. MAX som i dette tilfælde giver dig den største dato pr. kombination af dag_uge og dag_maaned.
startlinket.dk >> flse's formuleringer er ret præcise. Prøv at læse dem igen :o)
Jeg vil kommentere dit eksempel fra tidligere: >> SELECT DISTINCT dag_uge, dag_maaned FROM statistik WHERE >> maaned='$maaned' AND aar='$aar' ORDER BY dag_maaned
Selvom du anvender DISTINCT gennemløbes tabellen statistik kun een gang. Hvis en række opfylder dit kriterie (WHERE) trækkes værdierne dag_uge, dag_maaned ud som output. Hvis den samme kombination af dag_uge, og dag_maaned fremkommer flere gange bliver dette ignoreret.
Du har nu x kombinationer af dag_uge, dag_maaned. Ønsker du, at disse skal sorteres tilføjer du ORDER BY dag_maaned - eller hvad du måtte ønske som sortering.
I dit eksempel udvælger du to felter, men princippet er det samme, om du havde valgt 10 felter.
Efter at have siddet i flere timer og læst og læst det her igennem en masse gange, så tror jeg at jeg er ved at få lidt mere
styr på tingene.
1: I starten forstod jeg det sådan at der var en rækkefølge i DISTINCT, hvor den først fandt rækkerne som passede til den
første, men kun én af hver. Derefter fortsatte den med den næste og det kunne derved være med til at sætte antallet af rækker
endnu mere ned. Det var dog noget jeg havde misforstået og endelig har fået svar på, nemlig at det er kombinationen af de kolonner som står i
DISTINCT som bliver sammenlignet ved.
2: Så havde jeg fået at vide at man ikke kunne bruge ORDER BY sammen med GROUP BY, men det fik jeg dog at vide nu at man godt
kunne.
3: Jeg havde opdaget at GROUP BY også sorterede, men fik at vide at ORDER BY bare skulle bruges ganske normalt.
4: flse, du fortalte noget om at GROUP BY var mere ressurcetungt end DISTINCT, men du kom vidst lige til at skrive GROUP BY
ét sted, isteden for DISTINCT, hvilket jeg kunne regne mig frem til.
5: flse, du fortalte også at DISTINCT teknisk set var det samme som GROUP BY, hvilket fik mig til at spørge hvorfor man så
ikke bare altid brugte GROUP BY. Det mener jeg ikke rigtig jeg fik svar på, men fik at vide at GROUP BY skulle være mere
ressurcetungt, så det var vel også en form for svar. Du fortalte dog senere at de kolonner man valgte i SELECT i en GROUP BY query også skulle være med under GROUP BY, så dér
forsvant den fordel jo.
6: Her i dit sidste svar svarede du endelig på hvordan man skulle kunne trække andre data ud af rækken med samme query,
hvilket du sagde at man egentlig ikke rigtig kunne uden at DISTINCT ville tage den med i sine sorteringer, og derved ville
det jo heller ikke være smart hvis man blev nødt til at lægge "id" ind i DISTINCT, for at kunne få det unikke id for rækken
frem. For så ville det ikke virke. Du fortalte også noget med at man i GROUP BY ikke kunne skrive f.eks. "dato" under SELECT, hvis det ikke også var med i GROUP
BY, hvilket jeg ikke rigtig forstår hvorfor man ikke kan.
Men nu vil jeg mene at jeg har fået styr på det hele, hvis altså der ikke kommer en kommentar fra jer nu, som modsiger det
jeg lige har fundet ud af. Så sørg venligst for at skrive det så enkelt som muligt, så jeg ikke bliver forvirret igen. Tak.
GROUP BY kan det samme som DISTINCT, men også meget mere. Man bruger typisk ENTEN DISTINCT eller GROUP BY.
GROUP BY samler og behander rækker i grupper. ... GROUP BY x,y,z behandler alle rækker med samme kombination af x,y,z som en gruppe.
Man behøver IKKE at lave select på alle felter som definerer gruppen, men det vil man ofte gerne. SELECT x,y FROM tabel GROUP BY x,y,z; er ok
SELECT alder, count(*) AS antal from klasse GROUP BY alder; - Her defineres gruppen kun af feltet alder. Gruppen består af FLERE rækker. Rækkerne i gruppen har samme alder, men ikke samme højde. Det er derfor ikke lovligt at selecte højde, men lovligt at select sum(højde). SELECT alder, count(*) as antal, sum(hoejde) as samlethoejde from klasse GROUP BY alder;
Undskyld jeg først skriver nu, men jeg har ventet hele weekenden på at flse ville kommentere mit lange indlæg dér. Men det var godt at du lige kunne bekræfte hvad jeg skrev, nu sidder jeg dog tilbage og ikke ved hvordan jeg skal få fat i "dag_uge" også...
Jeg går ud fra at det overhovedet ikke kan være med under hverken en DISTINCT eller GROUP BY query, så må jeg vel bare lave endnu en query i min while, som finder det for de 31 dage i måneden?
startlinket.dk >> Det ser ud som om, at du efterhånden har forstået det meste. GROUP BY deler tabellen op i grupper. Grupperne udgøres af rækker, hvor visse felter er ens.
En select med GROUP BY kan KUN vise værdier, som er fælles for hver gruppe. Du kan IKKE samtidig udvælge enkeltværdier indenfor grupperne.
Jep, jeg har samtidig med her haft gang i en diskution på en nyhedsgruppe, hvor jeg kom frem til at der nok ikke var noget tidspunkt hvor jeg ikke bare kunne sætte den anden information jeg ville have ind i DISTINCT´en. Skulle det alligevel ske, så kan jeg jo altid lave endnu en query.
Men I skal have tak for hjælpen. ;)
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.