17. september 2002 - 20:01Der er
15 kommentarer og 1 løsning
group by og order by
Hej
Jeg har et problem med at få den rigtige sortering af et sql udtræk.
Min sql:
select * from galleri where galleri.visible=1 and galleri.FromDate>'xxxx-xx-xx' group by galleri.FromDate order by galleri.FromDate desc
Dette virker også fint men jeg vil gerne opnå en anden sortering af de data der groperes. Jeg vil have den record vist med det største nummer i feltet"view" viest.
Hos Computerworld it-jobbank er vi stolte af at fortsætte det gode partnerskab med folkene bag IT-DAY – efter vores mening Danmarks bedste karrieremesse for unge og erfarne it-kandidater.
Detter giver bare en anden sortering af det færdige resultat, det der skal være en anden sortering af det er af de felter der grouperes sammen til en. Det er den ene der skal være den med den største view, af alle dem der bliver fjernet ved group by.
Jeg har desværre ikke tid til at test syntaksen før senere, men måske illustrerer dette, hvad du mener: SELECT XXXX.* FROM XXXX, (SELECT nummer, MAX(view) AS max FROM XXXX WHERE XXXX.Visible=1) as maxviews WHERE XXXX.Nummer = maxviews.Nummer AND XXXX.View = maxviews.max AND XXXX.Visible=1 ORDER BY Navn DESC;
Gruppenringen finder max(view) for hver værdi (gruppe) af nummer. Du vil nu udvælge (og sortere) de rækker, hvor nummer har view=max(view).
Okay nu fatter jeg intet!! Hvis du gider prøve at lave det på mit rigtige sql udtryk ville det være kanon det er:
select * from galleri,places where galleri.visible>=1 and galleri.PlaceNo=places.ItemNo and galleri.FromDate>'2002-09-01' group by galleri.FromDate, galleri.PlaceNo, galleri.Serie order by galleri.fromdate desc
hwlarsen >> Jeg ved ikke, om du stadig er oppe. Jeg skulle lige have overstået min aftenløbetur :o) Du skriver: "Det er den ene der skal være den med den største view". I dit rigtige sql-udtryk, for hvilket felt vil du kun have de rækker med den højeste værdi?
Når man anvender GROUP BY, deles tabellens rækker op i grupper. I en SELECT med GROUP BY, skal alle værdierne i select-listen være: 1. med i GROUP BY delen ELLER 2. udtryk med aggregat funktioner ELLER 3. konstanter Databasen udfører aggregat funktionen på hvert udtryk i select-listen for hver gruppe af rækker og returnerer en enkelt resultatrække for hver gruppe.
Tag f.eks. tabellen xyz (x number, y number, z number). x y z 1 1 1 1 2 2 1 11 11 2 2 1 2 2 2 2 3 3 3 3 3
Når man skriver GROUP BY x,y - så vil det sige, at rækker med samme x-værdi og samme y-værdi tilhører samme gruppe.
SELECT x FROM xyz GROUP BY x; er det samme som SELECT DISTINCT x FROM xyz;
SELECT x,y FROM xyz GROUP BY x; FEJL! Vi opdeler i grupper, hvor x er ens. Der kan være flere forskellige y-værdier i hver gruppe.
SELECT x, MAX(y) AS max FROM xyz GROUP BY x; Helt OK! Selvom der er flere y-værdier for hver gruppe, så er der kun een maxværdi.
ORDER BY er først aktuel efter GROUP BY: SELECT x, MAX(y) AS max FROM xyz GROUP BY x ORDER by max DESC;
hwlarsen >> Humlen er, at når du bruger GROUP BY, så får du KUN aggregerede (dvs beregnede) værdier for hver gruppe af rækker samt de værdier, som identificerer selve gruppen. Det er IKKE det samme som at udvælge HELE enkelt-rækker. ORDER BY gør slet ingen forskel. Den sorterer kun, hvad der kommer ud af GROUP BY.
Prøv at se på mit 'kryptiske' SQL-udtryk længere oppe igen. Første trin står inde i parantesen. Ved hjælp af GROUP BY bestemmes max-værdien for hver gruppe. Output af denne parantes navngives maxviews. Andet trin er en join imellem maxviews og XXXX, som anvendes til at udvælge rækkerne, som indeholder max-værdierne.
Jeg prøver nu samme øvelse på dit SQL-udtryk. Der er nu to tabeller, og det fremgår ikke helt, hvad du gerne vil.
Kriterie: galleri.visible>=1 AND galleri.PlaceNo=places.ItemNo AND galleri.FromDate>'2002-09-01'
Gruppering: Vi ønsker grupperer efter galleri.PlaceNo, galleri.Serie og vi ønsker kun de rækker med højeste galleri.fromdate.
Dette select identificerer hvilke rækker vi er interesserede i: SELECT galleri.PlaceNo, galleri.Serie, MAX(galleri.bigview) AS maxview FROM galleri,places where galleri.visible>=1 AND galleri.PlaceNo=places.ItemNo AND galleri.FromDate>'2002-09-01' GROUP BY galleri.PlaceNo, galleri.Serie;
Nu pakker vi så den SELECT udenom, som udvælger rækkerne: SELECT * FROM galleri,places,( SELECT galleri.PlaceNo, galleri.Serie, MAX(galleri.bigview) AS maxview FROM galleri,places where galleri.visible>=1 AND galleri.PlaceNo=places.ItemNo AND galleri.FromDate>'2002-09-01' GROUP BY galleri.PlaceNo, galleri.Serie ) maxrows WHERE galleri.visible>=1 AND galleri.PlaceNo=places.ItemNo AND galleri.FromDate>'2002-09-01' AND galleri.bigview=maxrows.maxview AND galleri.PlaceNo=maxrows.PlaceNo AND galleri.Serie=maxrows.Serie;
Sortering: Hvis det er de korrekte data, kan du altid tilføje sortering til sidst: ... ORDER BY galleri.fromdate DESC;
Lidt supplerende kommentarer: "SELECT *" bør nok erstattes af navnene på de ønskede felter.
Den innerste select med GROUP BY kan evt. oprettes som et view. Så bliver det endelige SQL-udtryk meget mere overskueligt.
I mit oprindelige svar skrev jeg: "...) as maxview...". I Oracle (og sikkert også MySQL) skal "as" fjernes, ellers får man syntaksfejl.
Det kan jeg altså ikke få til at virke, jeg kan godt se ideen med det. Jeg har ladet mig fortælle at MySQL kun kan klare sql med et niveau, altså ikke med select i parantes.
Jeg vidste ikke, at MySQL havde begrænsninger i den retning. (Jeg bruger Oracle), men det problem tror jeg kan løses med mit tidligere forslag: "Den innerste select med GROUP BY kan evt. oprettes som et view. Så bliver det endelige SQL-udtryk meget mere overskueligt."
CREATE VIEW maxrows AS SELECT ...; (hele smøren i parantesen).
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.