Avatar billede kratluskeren Nybegynder
26. oktober 2004 - 17:42 Der er 32 kommentarer og
2 løsninger

avanceret order by

Hej
Findes der en lækkerfræk måde at definere en avanceret sorteringsrækkefølge af en SQL forespørgsel på?

Hvis jeg nu har en lang liste over datoer og ønsker mit udtræk sorteret således at jeg først får alle poster med "dato i dag og en uge frem". Dereftefter får alle poster hvor dato er blank og til sidst får resten.
Kan det lade sig gøre i en og samme forespørgsel?
En alm order by hjælper jo ikke meget her.

Bruger MySQL v3.23.58
Avatar billede hmortensen Nybegynder
26. oktober 2004 - 17:55 #1
Du blir nok nødt til at lave 3 forespørgsler:

De først 7 dage:
SELECT * FROM tabel WHERE (TO_DAYS(CURDATE( )) - TO_DAYS(dato)) <= 7

Og her resten:
SELECT * FROM tabel WHERE (TO_DAYS(CURDATE( )) - TO_DAYS(dato)) > 7

Og NULL værdier:
SELECT * FROM tabel WHERE dato IS NULL
Avatar billede kratluskeren Nybegynder
26. oktober 2004 - 19:23 #2
Problemet med dette er at jeg får 3 recordsets ud af det i min asp kode, og jeg vil kun have et hvor det hele ligget samlet, men sorteret på nævnte måde.
Tænkte på om der var en smart SQL ting man kunne lave fremfor at kode sig ud af det på en lidt halvklodset måde.
Avatar billede hmortensen Nybegynder
26. oktober 2004 - 19:33 #3
Jeg kan ikke se problemet i det, men ok, du kan da lave et nyt array med alle 3 udtræk, hvis du helst kan li det på den måde
Avatar billede kratluskeren Nybegynder
26. oktober 2004 - 19:38 #4
Jeg har behov for at det hele ligger i samme recordset, da jeg skal andet en blot udskrive det hele på en gang.

Findes der en løsning hvor den laver disse tre udtræk og fylder i samme recordset så?
...eller skal vi ud i noget array af en slags
Avatar billede arne_v Ekspert
26. oktober 2004 - 19:44 #5
Du kan prøve at kombinere med:

SELECT *
FROM tabel
ORDER BY
CASE
WHEN (TO_DAYS(CURDATE( )) - TO_DAYS(dato)) <= 7 THEN 1
WHEN dato IS NULL THEN 2
WHEN (TO_DAYS(CURDATE( )) - TO_DAYS(dato)) > 7 THEN 3
END
Avatar billede kratluskeren Nybegynder
27. oktober 2004 - 21:33 #6
Hey arne_v
Det ser sq smart ud. Det var noget i den stil jeg var ude efter. Jeg kan dog ikke helt for den til at virke. Det ser ud til at den bare ryster posen og spytter posterne ud lidt tilfældigt. Er du sikker på den er korrekt?
Avatar billede arne_v Ekspert
27. oktober 2004 - 21:35 #7
Jeg er absolut ikke sikker. Det var bare hvad jeg synes så logisk ud.
Avatar billede hmortensen Nybegynder
27. oktober 2004 - 21:39 #8
Det virker fint her
Avatar billede arne_v Ekspert
27. oktober 2004 - 21:41 #9
Men du er måske på en nyere versione end v3.23.58 ?
Avatar billede hmortensen Nybegynder
27. oktober 2004 - 21:42 #10
Nøjagtig samme version
Avatar billede kratluskeren Nybegynder
27. oktober 2004 - 22:24 #11
Hmm måske er det bare mig der klokker lidt i det.


orderSQL = "ORDER BY CASE "
    orderSQL = orderSQL& " WHEN (TO_DAYS(CURDATE( )) - TO_DAYS(Saelger_Aftaledato)) <= 7 THEN 1"
    orderSQL = orderSQL& " WHEN Saelger_Aftaledato = '9999-01-01' THEN 2"
    orderSQL = orderSQL& " WHEN (TO_DAYS(CURDATE( )) - TO_DAYS(Saelger_Aftaledato)) > 7 and (Saelger_Aftaledato <> '9999-01-01') THEN 3"   
    orderSQL = orderSQL& " END"

Giver dette resultat:
01-01-9999
01-01-9999
29-10-2004
01-01-9999
01-01-9999
01-01-9999
01-01-9999
Avatar billede hmortensen Nybegynder
27. oktober 2004 - 22:45 #12
Står dine datoer sådan her 01-01-9999 ?
Avatar billede kratluskeren Nybegynder
27. oktober 2004 - 22:46 #13
Nej, jeg har bare skrevet dem ud sådan. I mySQL står de åååå-mm-dd
Avatar billede majkat Nybegynder
29. oktober 2004 - 10:01 #14
WHEN (TO_DAYS(CURDATE( )) - TO_DAYS(Saelger_Aftaledato)) <= 7 THEN 1

hint: hvad hvis nu Saelger_Aftaledato = '9999-01-01' ?

:-)
Avatar billede hmortensen Nybegynder
29. oktober 2004 - 10:03 #15
Så er der ret lang tid til :)
Avatar billede kratluskeren Nybegynder
29. oktober 2004 - 11:13 #16
Jamen 9999-01-01 skal svare til at den er blank. Man har bare valgt at dette felt skal være udfyldt, så jeg kalder den 01-01-9999, hvis den ikke er defineret.

Giver det mening?
Dvs. sorteringen skal ske således.
1 - alle dem der har dato i dag eller en uge frem
2 - alle dem der er 9999-01-01
3 - resten, sorteret efter dato - nyeste først
Avatar billede hmortensen Nybegynder
29. oktober 2004 - 11:14 #17
Hvorfor 9999-01-01, når du bare kan gi feltet en NULL værdi ?
Avatar billede kratluskeren Nybegynder
29. oktober 2004 - 11:19 #18
tja, det er ikke mit valg. Der er ønske om at feltet altid indeholder en datoværdi af en slags. Jeg kunne også have kaldt den 0000-00-00, men det er samme situation.

Uanset hvad, må løsningen da være den samme uanset om der står null eller 9999-01-01
Avatar billede majkat Nybegynder
29. oktober 2004 - 11:20 #19
Det gir (en slags) mening, men du skal sørge for at det AND... check du har i CASE ... 3 også bliver lavet i 1'eren.

Må nu sige, at jeg også er tilhænger af NULL...

I øvrigt er det ikke helt nok -- du skal også bruge den faktiske dato i din ORDER BY, ellers kommer de tre grupper ud hulter til bulter. Så

  ORDER BY CASE ... END, Saelger_Aftaledato

må vist være det du er ude efter
Avatar billede hmortensen Nybegynder
29. oktober 2004 - 11:24 #20
Der er forskel på 0000-00-00 og NULL
Ved NULL har felten slet ingen værdi og kan tjekkes ved (IS NULL) / (IS NOT NULL)
Avatar billede kratluskeren Nybegynder
29. oktober 2004 - 11:38 #21
Hej igen
Det er klart at der er forskel på null og en dato.
Tænkte jeg kunne løse det på denne måde:
WHEN Saelger_Aftaledato = '9999-01-01' THEN 2

Den mystiske sortering kunne faktisk godt skyldes det manglende, Saelger_Aftaledato
Det vil jeg lige teste når jeg er ved systemet igen, så vender jeg tilbage herefter :)
Avatar billede kratluskeren Nybegynder
31. oktober 2004 - 16:10 #22
ORDER BY CASE WHEN (Saelger_Aftaledato >= CURDATE() and Saelger_Aftaledato < CURDATE() + INTERVAL 7 DAY) THEN 1
WHEN (Saelger_Aftaledato = '9999-01-01') THEN 2 else 3 END, Saelger_Aftaledato asc

Så virker det sq. Mange tak for hjælpen begge to. Jeg vil gerne fordele points mellem jer så smid et svar begge to.

Det tager dog en krig at foretage denne søgning når der er mange poster i tabellen. Meget længere tid end en almindelig "order by Saelger_Aftaledato" færdig slut.

Kan der gøres noget for det?
Avatar billede hmortensen Nybegynder
31. oktober 2004 - 16:12 #23
Jeg ved ikke om det kan optimeres, men det gør arne måske
Avatar billede arne_v Ekspert
31. oktober 2004 - 16:13 #24
Tror jeg ikke. Den form for beregning koster.

Hvis du skal bruge den rigtigt meget, så kan du overveje at lave en kolonne
med den værdi og så kun beregne den for en kolonne ved INSERT, så vil ORDER BY
nok være noget hurtigere.

Og et svar.
Avatar billede arne_v Ekspert
31. oktober 2004 - 16:14 #25
... så kun beregne den for en række ved INSERT ...
Avatar billede kratluskeren Nybegynder
31. oktober 2004 - 16:16 #26
Takker :)
Avatar billede kratluskeren Nybegynder
31. oktober 2004 - 16:17 #27
Jeg forstår ikke helt den løsning arne_v, men det er sikkert smart. Vil du uddybe?
Avatar billede majkat Nybegynder
31. oktober 2004 - 16:24 #28
Du har vel et indeks på Saelger_Aftaledato?

Du kan nok optimere en smule ved at sørge for at de oftest forekommende tilfælde står først i din CASE. F.eks, hvis  '9999-01-01' er den oftest forekommende værdi, skal WHEN ... 2 stå først. Jeg kan forestille mig, at din WHEN ... 1 case er den *sjældnest* forekommende, så den bør være til sidst.

Men det er nok ikke mange splitsekunder du sparer på dén konto...
Avatar billede kratluskeren Nybegynder
31. oktober 2004 - 16:28 #29
det giver faktisk ikke rigtig noget majkat. Øv.
Ville det have betydning for dette problem hvis jeg brugte null i stedet for 9999-01-01?
Avatar billede majkat Nybegynder
31. oktober 2004 - 16:34 #30
nu da du ikke bekræftede...

  Du har vel et indeks på Saelger_Aftaledato?

Det vil være den absolut største optimering du kan gøre.

At lave 9999-01-01 om til NULL vil give noget - men hvor meget ved jeg ikke. Og hvis du allerede har udviklet meget i din applikation, ville jeg personligt være forsigtig med at gå ind at ændre noget. Nogen gange må man bare leve med en uheldig designbeslutning :-(
Avatar billede kratluskeren Nybegynder
31. oktober 2004 - 16:43 #31
Ups fik ikke lige svaret.
Jeg har indexeret, så her kan jeg desværre ikke hente noget.
Hvis ikke det vil give det store at rette dato til null er det vist ikke besværet værd.

Jeg takker mange gange for hjælpen :D
Avatar billede arne_v Ekspert
31. oktober 2004 - 16:51 #32
Hvis du laver et felt sorthelp integer i tabellen og ved indsæt sætter den til
rette værdi, så er det hurtigere a sortere efter.

Men det er noget vrøvl fordi feltets værdi skal ændres som tiden går.

Men så kunne så kunne du:
  - tilføje feltet sorthelp integer
  - køre et job lige efter midnat som sætter værdien af feltet med e UPDATE
så vil en query ORDER BU sorthelp,dato nok køre noget hurtigere.

Giver selvfølgelig kun mening hvis queryen skal køres mange gang i løbet af dagen.
Avatar billede kratluskeren Nybegynder
31. oktober 2004 - 17:22 #33
Der er faktisk smart, men også lidt en ufed løsning.

Jeg finder ud af noget. Mange tak for hjælpen alle sammen
Avatar billede arne_v Ekspert
31. oktober 2004 - 17:32 #34
Ikke så kønt.

Men sommetider må man bøje reglerne lidt for at få den performance man har brug for.
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