Avatar billede lsskaarup Nybegynder
20. december 2005 - 16:28 Der er 36 kommentarer og
1 løsning

Hjælp til sortering

Jeg har en lidt tricky sortering, som jeg helst skal have DB til at gøre for mig.

Data kommer fra et intranet system, så jeg har lidt svært ved at vise jer noget.

Men jeg har 2 felter til datoer vedrørende en ordre. Henholdsvis en deadline og en reelt udfyldelsesdato. Når jeg hiver data ud fra DB, så skal den sortere det efter følgende metode:

Ordre der IKKE er udført, med dem tættest på deadline øverst.
Ordre der ER udført, med dem der overskred deadline mest øverst.
Ordre der endnu ikke har fået en deadline.

Felternes struktur er følgende:
Deadline:
Navn: r530b. Standardværdi: NULL.

Udførte:
Navn: r542a. Standardværdi: NULL.

Begge kan selvfølgelig indeholde en dato samt 0000-00-00, som skal sidestilles med NULL.

Min query ser indtil videre sådan ud:

SELECT o.id as id, o.ordre as ordre, o.rev as rev, o5.r530b, o5.r542a FROM ordre AS o, ordre0 AS o0 LEFT JOIN ordre5 AS o5 ON o0.tilbudsnummer=o5.tilbudsnummer WHERE o0.tilbudsnummer=o.id && (o5.r534=0 || o5.r534 IS NULL) && o5.r534a = 0 && (o5.r554=0 || o5.r554 IS NULL) ORDER BY

Men mangler altså lige ORDER BY delen.
Avatar billede Slettet bruger
21. december 2005 - 10:52 #1
Det var godt nok en lidt bøvlet sortering. Her er mine første tanker om din ønskede orden - mest for lige at være sikker:

Først rækker med
  (o5.r542a IS NULL OR o5.r542a = '0000-00-00')
  AND
  (o5.r530b IS NOT NULL AND o5.r530b !='0000-00-00')
ordnet efter o5.r530b ASC

Dernæst rækker med
  (o5.r542a IS NOT NULL AND o5.r542a != '0000-00-00')
ordnet efter en af disse
  (o5.r542a - o5.r530b) DESC
  (o5.r530b - o5.r542a) ASC

Og til sidst rækker med
  (o5.r530b IS NULL OR o5.r530b = '0000-00-00')

Forresten: Kan der forfindes ordrer, der er udført uden at have fået en deadline?
Avatar billede lsskaarup Nybegynder
21. december 2005 - 11:34 #2
Ja, en bøvlet sortering det må du nok sige, den har også drillet mig et pænt stykke tid nu. Men lige for at uddybe.

Vi har altså 2 datoer, en der viser deadline og en til datoen hvor opgaven blev udført. Vi har så en oversigt der viser alle ordre, og det er denne der bl.a. skal kunne sorteres efter de 2 datoer. Så først vi de have:
            /  Ordre hvor deadline er overskredet
Ikke udført -    Ordre hvor der er 1-4 dage til deadline
            \  Resten af ordrene der ikke er udført

        /  Ordre der blev udført efter deadline
Udført -    Ordre der blev udført 1-4 dage før deadline
        \  Resten af ordrene der er udført

Begge skal det være sådan, at ordren der er overskredet med 1 dag kommer før den der har 4 dage til deadline, som igen kommer før ordren der har 20 dage til deadline.

Og, ja desværre kan der godt forkomme ordrer, som er udført men som ikke have en deadline.

Men kigger lige på din sortering, men som jeg lige umiddelbart forstår den, så tror jeg ikke den passer helt.
Avatar billede Slettet bruger
21. december 2005 - 11:49 #3
Mine forslag burde passe til din første beskrivelse, men under forudsætning af at udførte ordrer har en deadline.

I din nye beskrivelse er endnu ikke udførte ordrer uden deadline kommet op før de udførte, hvor de i den oprindelige beskrivelse lå bagefter. Hvis den nye beskrivelse er korrekt, vil det faktisk gøre sorteringen lidt mere simpel.
Avatar billede lsskaarup Nybegynder
21. december 2005 - 11:59 #4
Hov, nej så er det mig, der forvirrer dig.

Ordre der ikke er udførte og ikke har en deadline skal helst være sidst.
Avatar billede lsskaarup Nybegynder
21. december 2005 - 12:04 #5
Min ORDER BY ser pt sådanne ud:

(o5.r542a IS NULL OR o5.r542a = '0000-00-00') AND (o5.r530b IS NOT NULL AND o5.r530b !='0000-00-00'), o5.r530b ASC, (o5.r542a IS NOT NULL AND o5.r542a != '0000-00-00'), (o5.r530b - o5.r542a) ASC, (o5.r530b IS NULL OR o5.r530b = '0000-00-00')

og der kommer de ikke sorteret rigtigt.
Avatar billede lsskaarup Nybegynder
21. december 2005 - 12:12 #6
Ahh, der ligger en del ordre, som ikke har fået opdateret deres data i forhold til disse felter. Jeg laver lige en oprydning, for at se om det hjælper.
Avatar billede lsskaarup Nybegynder
21. december 2005 - 15:12 #7
Nej, det dur ikke helt endnu
Avatar billede lsskaarup Nybegynder
21. december 2005 - 15:14 #8
Nå, tager sql'en direkte fra db'en så får jeg et andet resultat end når jeg henter det gennem php ?-|
Avatar billede lsskaarup Nybegynder
21. december 2005 - 15:44 #9
Nå, jeg kan få phpmyadmin til at vise forskellige resultater fra samme query, egentlig godt klaret, men tilbage til sorteringen, som jeg mener ikke virker helt perfekt endnu.

Den skal reel sortere dem således:

  r542a (deadline)                      r530b (udført)

NULL/0000-00-00                  Dato(Mest overskredne øverst)
Dato(tættest på deadline øverst)  Dato
Dato                              NULL/0000-00-00
NULL/0000-00-00                  NULL/0000-00-00

Linie 2 og 3 skal flettes samme, så de ordre der ingen deadline har med er udførte, bare bliver sorteret efter/sammen med linie 2. Den sidste linie, ved jeg pt. ikke helt præcist hvor de vil have, om den skal være helt øverst eller helt nederst.
Avatar billede lsskaarup Nybegynder
21. december 2005 - 16:05 #10
Hold da k..., jeg har jo helt glemt datoforskellen. Hvis jeg gerne vil have den til at sortere dem der er mest overskredne øverst, så skal du da have et felt som viser hvor meget det er overskredet.

date530b returner forskellen fra deadline til dags dato.
Avatar billede lsskaarup Nybegynder
21. december 2005 - 16:29 #11
Hmm, jeg paster lige hele min query. Den er lidt stor men se bort fra alt andet end de felter der har været bragt på bane.

SELECT o5.r542a, o5.r530b, (TO_DAYS(o5.r530b)-TO_DAYS(NOW())) AS date530b, o.id as id, o.ordre as ordre, o.rev as rev, concat(WEEKOFYEAR(o5.r542a), '-', DAYOFWEEK(o5.r542a)-1) AS statik, concat(WEEKOFYEAR(o5.r543a), '-', DAYOFWEEK(o5.r543a)-1) AS optegn, concat(WEEKOFYEAR(o5.r544a), '-', DAYOFWEEK(o5.r544a)-1) AS godkendt, WEEKOFYEAR(o5.r533c) AS lev, o5.r555 AS levtegn, concat(WEEKOFYEAR(o5.r530b), '-', DAYOFWEEK(o5.r530b)-1) AS deadSta, concat(WEEKOFYEAR(o5.r531b), '-', DAYOFWEEK(o5.r531b)-1) AS deadOp, concat(WEEKOFYEAR(o5.r577), '-', DAYOFWEEK(o5.r577)-1) AS nyDeadOp, concat(WEEKOFYEAR(o5.r532b), '-', DAYOFWEEK(o5.r532b)-1) AS deadGod, o0.r1 as projektleder, o0.r9 as kunde, o0.r18 as bygherre, o5.r540a, o5.r541, o5.r541a, o5.r542, o5.r580, o5.r543, o5.r531b, o5.r532b, o5.r539, DAYOFWEEK(o5.r547a)-1 AS godUgedag, WEEK(o5.r547a) AS godUge, o5.r544, o5.r548, o5.r552, o5.r571, o5.r572, o5.r573, o5.r574, o5.r575, o5.r555, o5.r575a, o5.r580a, datediff(o5.r530b, o5.r542a) AS date542a, (TO_DAYS(o5.r531b)-TO_DAYS(o5.r543a)) AS date543a, (TO_DAYS(o5.r532b)-TO_DAYS(o5.r544a)) AS date544a, (TO_DAYS(o5.r531b)-TO_DAYS(NOW())) AS date531b, (TO_DAYS(o5.r532b)-TO_DAYS(NOW())) AS date532b, o5.r543a, o5.r544a FROM ordre AS o, ordre0 AS o0 LEFT JOIN ordre5 AS o5 ON o0.tilbudsnummer=o5.tilbudsnummer WHERE o0.tilbudsnummer=o.id && (o5.r534=0 || o5.r534 IS NULL) && o5.r534a = 0 && (o5.r554=0 || o5.r554 IS NULL) ORDER BY (o5.r542a = '0000-00-00' OR o5.r542a IS NULL) AND (o5.r530b IS NOT NULL OR o5.r530b != '0000-00-00'), date530b DESC

Tester jeg den i phpmyadmin, så er det som om det ignorerer (o5.r542a = '0000-00-00' OR o5.r542a IS NULL). For den første post har en rigtigt dato i feltet, f.eks. 2005-10-03

Burde den ikke tage den med i overvejelserne også?
Avatar billede Slettet bruger
21. december 2005 - 17:30 #12
Der er nødt til at være noget, der styrer rækkefølgen, og de forskellige ordener:

IF(
    (o5.r542a IS NULL OR o5.r542a = '0000-00-00')
    AND
    (o5.r530b IS NOT NULL AND o5.r530b !='0000-00-00'),
    1,
    IF(
        (o5.r542a IS NOT NULL AND o5.r542a != '0000-00-00'),
        2,3
      )
  ) ASC

Den får dem ud i de tre hovedgrupper. Der er ingen speciel brug for at beregne afstanden fra nu til deadline, for alle ikke-uførte opgaver med en fastsat deadline skal jo bare vises i rækkefølge efter deadline - med ældst først.

Så kommer blokken, der står for sorteringen indenfor de enkelte grupper:

IF(
    (o5.r542a IS NULL OR o5.r542a = '0000-00-00'),
    o5.r530b, o5.r530b - o5.r542a
  ) ASC

Så ialt skulle det være klaret med denne klump:

ORDER BY IF((o5.r542a IS NULL OR o5.r542a = '0000-00-00') AND (o5.r530b IS NOT NULL AND o5.r530b !='0000-00-00'), 1, IF((o5.r542a IS NOT NULL AND o5.r542a != '0000-00-00'),2,3)) ASC, IF((o5.r542a IS NULL OR o5.r542a = '0000-00-00'),o5.r530b, o5.r530b - o5.r542a) ASC

Muligvis skal de if-blokke op i SELECT-delen og have navne, og så bruges med navnene i ORDER BY delen.
Avatar billede lsskaarup Nybegynder
22. december 2005 - 08:50 #13
Jubiii, sådan nu virker det næsten.

Den sorterer fint på ordre som kun har en deadline. Men på ordre som er udført er der enkelte fejl. Her skal den også sortere tidsmæssigt i forhold til deadlinen. Så den der er overskredet med er øverste og så falder de, men der er enkelte ordre som bryder sorteringen.

Grunden til at jeg kan se det lyn hurtigt, skyldes at på oversigten returnerer jeg en datokode (ugenr. - ugedagsnr.) for enten deadlinen eller udførslen. Først vises deadlinen og når opgaven er udført vises udførselsdatoen. Disse bliver også vist ved nogle farvekoder. Rød, gul og grøn alt efter for tæt på deadline ordren er eller blev udført.

Og problemet er at jeg kan se enkelte gule udførte ordre imellem de grønne, og alle gule skal ligge før de grønne, lige som de røde skal ligge før de gule. Det sidste ser dog ud til at virke.
Avatar billede lsskaarup Nybegynder
22. december 2005 - 13:51 #14
Okay, det er helt præcist o5.r530b - 05.r542a delen som ikke bliver sorteret rigtigt
Avatar billede Slettet bruger
23. december 2005 - 10:29 #15
Jeg så lige, at du allerede udregner en datediff på de to felter, så prøv at erstatte

o5.r530b - o5.r542a

med

date542a
Avatar billede lsskaarup Nybegynder
23. december 2005 - 11:36 #16
Det kan jeg ikke fordi den kan finde uf at jeg navngiver "nye" felter.
Avatar billede Slettet bruger
23. december 2005 - 11:40 #17
Ok, så skriver du bare

DATEDIFF(o5.530b, o5.542a)

i stedet for o5.r530b - o5.542a eller date542a
Avatar billede lsskaarup Nybegynder
23. december 2005 - 15:38 #18
Okay, jeg skal dog lige have sat det hel op her hjemme.
Avatar billede lsskaarup Nybegynder
03. januar 2006 - 10:10 #19
??? ehhh, jeg lagde ellers et indlæg i går, men nu er der har ikke ???

Så må jeg jo bare prøve igen.

Det hjalp ikke med DATEDIFF().

Den blander stadig væk enkelte ordre der er udførte.
Avatar billede Slettet bruger
03. januar 2006 - 15:53 #20
Måske kan det hjælpe mig lidt til at få den løst, hvis jeg lige ser eksempel på et udtræk fra databasen, som bliver sorteret forkert.
Avatar billede lsskaarup Nybegynder
03. januar 2006 - 16:35 #21
Prøver om det ser godt nok ud.

Først definationerne, som de kommer ud:
date530b_542a r542a r530b date530b id ordre rev statik optegn godkendt lev levtegn deadSta deadOp nyDeadOp deadGod projektleder kunde bygherre r540a r541 r541a r542 r580 r543 r531b r532b r539 godUgedag godUge r544 r548 r552 r571 r572 r573 r574 r575 r555 r575a r580a date542a date543a date544a date531b date532b r543a r544a

Derefter noget af data, vil ikke tage det hele da der er over 300 poster. Nok lidt for meget for at finde 4-5 stk. som ikke gør som de skal ;-)

198 2005-08-12 2005-10-10 -85 522 40788 0 32-5 NULL NULL 50  41-1 42-1 32-6 43-1 11936 P. Knudsen Trælast & Byggecenter A/S Aubo 0000-00-00 0 0 1 0 0 2005-10-17 2005-10-24 0 NULL NULL 0 0 0 0 1 1 1 1  0 0000-00-00 59 NULL NULL -78 -71 0000-00-00 0000-00-00

2 2005-09-23 2005-09-25 -100 600 40863 0 38-5 NULL NULL 45  38-0 39-6 39-6 40-4 11936 Haarby Trælast Hans Erik. Kærsgaard. Nygaardsvej. Jordløse. 568... 0000-00-00 0 0 1 1 0 2005-10-01 2005-10-06 0 NULL NULL 0 0 0 1 1 1 1 1  0 2005-09-23 2 NULL NULL -94 -89 0000-00-00 0000-00-00

2 2005-10-03 2005-10-05 -90 655 40913 0 40-1 41-1 NULL 48  40-3 41-2 41-2 42-1 12120 Stålia Hall Frank Heed 0000-00-00 0 1 1 1 1 2005-10-11 2005-10-17 0 5 41 0 1 0 0 1 1 1 1  0 2005-10-07 2 1 NULL -84 -78 2005-10-10 0000-00-00

203 2005-08-02 2005-10-05 -90 564 40829 0 31-2 41-5 NULL 47  40-3 41-5 41-1 42-5 11981 Team Baucenter Eggebek Hans-Joachim Steen 0000-00-00 0 1 1 1 1 2005-10-14 2005-10-21 0 NULL NULL 0 0 0 0 0 1 1 1  0 2005-08-17 64 0 NULL -81 -74 2005-10-14 0000-00-00

Den første bliver vist i grøn, men nr 2 og 3 bliver vist med gult. Altså er det lavet under 4 dage før deadline, hvilket også kan ses med det første punkt, da der står 2. Den sidste er grøn, altså er den lavet i god tid, helt præcist 203 dage før.

Jeg har taget et screendump af udtrækket fra db, men kan først ligge det op når jeg kommer hjem.
Avatar billede lsskaarup Nybegynder
03. januar 2006 - 22:22 #22
Få fik jeg lagt noget op. 24 timer skulle lige overståes ;-)

http://www.larsskaarup.dk/exp/sortering.htm
Avatar billede Slettet bruger
04. januar 2006 - 09:11 #23
Jeg prøver at se, om jeg kan gennemskue, hvad der forårsager fejlen.
Avatar billede lsskaarup Nybegynder
04. januar 2006 - 12:35 #24
Jeg var selv i går ved at ændre på nogle af IF-sætningerne, men det hjalp ikke meget og så kom "de tomme" pludselig op øverste også, så nej det virkede ikke. Håber du kan finde et eller andet.
Avatar billede lsskaarup Nybegynder
12. januar 2006 - 12:02 #25
Kan du gennemskue problemet?
Avatar billede lsskaarup Nybegynder
02. februar 2006 - 08:25 #26
Hallo, er du der, sandbox??
Avatar billede Slettet bruger
03. februar 2006 - 22:11 #27
Undskyld, jeg har haft så travlt i sidste måned, at jeg helt glemte at følge med her.
Avatar billede lsskaarup Nybegynder
04. februar 2006 - 19:52 #28
Det er i orden, vi kan jo alle få travlt. Men tror du, du kan kringle den og løse det sidste? Så ville jeg i hvert fald blive meget glad.
Avatar billede lsskaarup Nybegynder
24. marts 2006 - 08:24 #29
?????
Avatar billede Slettet bruger
26. marts 2006 - 14:00 #30
Nu kunne jeg pludselig se, hvad det skyldes - håber jeg da.

Det er det første tal, på rækken, der sorteres efter, og af en eller anden grund, bliver det sorteret som en streng i stedet for som et nummer. Det er derfor 2 kommer mellem 198 og 203

Det er den anden if, som skal rettes til så:

IF((o5.r542a IS NULL OR o5.r542a = '0000-00-00'),o5.r530b, o5.r530b - o5.r542a) ASC

Bagefter skal den se således ud:

CAST(IF((o5.r542a IS NULL OR o5.r542a = '0000-00-00'),o5.r530b, o5.r530b - o5.r542a) AS  SIGNED) ASC
Avatar billede lsskaarup Nybegynder
26. marts 2006 - 14:24 #31
Fint, håber det hjælper, det er i hvert fald en logisk forklaring. Prøver i næste uge.
Avatar billede lsskaarup Nybegynder
27. marts 2006 - 09:06 #32
Yes, nu har jeg gjort så den eneste sortering jeg har er din CAST, og så ser det ud til at virke, næsten. Der er lige nogle enkelte 0000-00-00, som kommer ind imellem reelt udfyldte datoer.
Avatar billede lsskaarup Nybegynder
27. marts 2006 - 10:24 #33
Nå det er fordi 530b - 542a giver 0, da de begge er 0000-00-00, nå der skal lige lægges et tjek ind for dette.
Avatar billede Slettet bruger
27. marts 2006 - 17:19 #34
Skal du ikke stadig bruge resten af sorteringen fra 21/12-2005 17:30:25?

Det var kun den sidste af IF-erne i den ORDER BY, som skulle laves om til den CAST.
Avatar billede lsskaarup Nybegynder
27. marts 2006 - 19:48 #35
Jo selvfølgelig, hvad fa.... tænkte jeg på.

Men sådan nu virker det, så håber jeg bare ikke de finder på en anden måde det skal sorteres på.

Tak for hjælpen og smid et svar, der vanker lidt ekstra, for at du hang på til enden.
Avatar billede Slettet bruger
27. marts 2006 - 19:57 #36
Jeg var faktisk lige ved at give op og melde pas, da jeg pludselig fik øje på at de bare blev sorteret alfabetisk i stedet for numerisk.
Avatar billede lsskaarup Nybegynder
28. marts 2006 - 08:07 #37
Det har godt nok også været en stor omgang
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