19. maj 2007 - 10:25Der er
9 kommentarer og 2 løsninger
Sortering på joinede tabeller
Hej Eksperter
Jeg vil gerne kunne sortere på en vilkårlig kolonne, i et udræk fra f.eks. 2 tabeller.
Eksempel: FOR REC IN(SELECT A.ET,A.TO,B.ALFA||' '||B.BETA AS AB FROM A, B WHERE A.TRE=B.ID ORDER BY CASE k_sort WHEN 'et' THEN A.ET WHEN 'to' THEN A.TO WHEN 'ab' THEN AB END ASC)
Tror det er min CASE sektion der brokker sig. Compileren brokker sig over at AB ikke er af samme type som A.Et og A.TO, selvom alle felterne bortset fra A.TRE og B.ID er VARCHAR2
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
FOR REC IN(SELECT * FROM (SELECT A.ET,A.TO,B.ALFA||' '||B.BETA AS AB FROM A, B WHERE A.TRE=B.ID ORDER BY CASE k_sort WHEN 'et' THEN A.ET WHEN 'to' THEN A.TO END ASC) ORDER BY CASE k_sort WHEN 'ab' THEN AB END ASC) LOOP --asjfsfaofasnrf END LOOP;
Lader spørgsmålet stå åbent. Kan jo være i kender en smartere metode.
Umiddelbart lyder det som om du bare skulle have gentaget concatineringen af de felter fra SELECT som danner feltet AB nede i CASE strukturen under ORDER BY:
FOR REC IN(SELECT A.ET,A.TO,B.ALFA||' '||B.BETA AS AB FROM A, B WHERE A.TRE=B.ID ORDER BY CASE k_sort WHEN 'et' THEN A.ET WHEN 'to' THEN A.TO WHEN 'ab' THEN B.ALFA||' '||B.BETA END ASC)
Så ku' du jo prøve at konvertere værdierne til tekst med funktionen TO_CHAR før du sætter dem sammen:
FOR REC IN(SELECT A.ET,A.TO,B.ALFA||' '||B.BETA AS AB FROM A, B WHERE A.TRE=B.ID ORDER BY CASE k_sort WHEN 'et' THEN A.ET WHEN 'to' THEN A.TO WHEN 'ab' THEN TO_CHAR(B.ALFA)||' '||TO_CHAR(B.BETA) END ASC)
Har fundet ud af at det ikke kun er på joinede tabeller problemet opstår.
FOR REC IN(SELECT A,B FROM C ORDER BY CASE D WHEN 'a' THEN A --NUMBER WHEN 'b' THEN B --VARCHAR2 END) LOOP --some stuff END LOOP;
Vil give samme problem, da de ikke er samme type. Hvis jeg konverterer med TO_CHAR vil sorteringen på numrene blive alfanumerisk, hvilket ikke er ønskeligt i dette tilfælde.
Synes godt om
Slettet bruger
20. maj 2007 - 15:24#7
Hvordan vil du egentlig have at sorteringen skal være? A og B er nødt til at være samme type, hvis du skal kunne sortere på dem. Hvis alfanumerisk sortering ikke er godt nok, er det så fordi at A-værdierne kommer ind et forkert sted?
Du kunne måske konkatener en alfanumerisk værdi til B, så den kommer ind rigtigt i forhold til A'erne:
WHEN 'a' THEN 'AAAAAAAA' || A WHEN 'b' THEN B ....
Eller også kunne du formatere A til en varchar2 af samme længde som maksimal længde af B, med foranstillede mellemrum eller 0'er:
WHEN 'a' THEN TO_CHAR ( A, 'FM00000000000000000000000' )
(FM betyder fillmode. Dvs. ingen mellemrum inden start på konverteret streng)
Tjah. Så er spørgsmålet hvad der er enklest Reelt har jeg 3 kolloner af typen NUMBER 5 kolonner af typen VARCHAR2 2 kolloner af typen DATE
Hvad vil i mene er simplest i når, jeg gerne vil give brugeren muligheden for at sortere på én vilkårlig kollonne?
Mit bud: FOR REC IN (SELECT * FROM (SELECT * FROM (SELECT * FROM Z ORDER BY CASE Y WHEN 'a' THEN A --NUMBER WHEN 'b' THEN B --NUMBER WHEN 'c' THEN C --NUMBER END) CASE Y WHEN 'd' THEN D --VARCHAR2 WHEN 'e' THEN E --VARCHAR2 WHEN 'f' THEN F --VARCHAR2 WHEN 'g' THEN G --VARCHAR2 WHEN 'h' THEN H --VARCHAR2 END) CASE Y WHEN 'i' THEN I --DATE WHEN 'j' THEN J --DATE END) LOOP --some stuff END LOOP;
Jeg er lidt grøn hvad PL/SQL angår. Hvad mener i er mest optimalt?
Synes godt om
Slettet bruger
20. maj 2007 - 19:33#9
jeg tror ikke at dit bud vil virke. Du nøjes med at sortere først tal, så varchar og så dates. Men hvordan undgår du at allerede sorterede rækker ikke bliver tilfældigt gensorteret af den næste SELECT-statement?
Og hvad sker der egentlig, når du laver en ORDER-BY, der ikke tager hensyn til alle værdier (i så fald giver din case-sætning værdien NULL, som sorteres sidst)? I dit inderste statement sorterer du på Y-er, hvor Y er a, b eller c. Men hvordan reagerer din ORDER-BY på alle de andre Y-er? Skal du ikke i det mindste have en ELSE-del:
CASE Y WHEN 'a' THEN A --NUMBER WHEN 'b' THEN B --NUMBER WHEN 'c' THEN C --NUMBER ELSE -1 END)
Kort sagt: Din statement er ikke så simpel at tolke, som den ser ud. Du bliver da nødt til at sortere alle værdier på een gang. Vil du have dem sorteret som først a-er, så b-er, så c-er ... og tilsidst alle j-er? Så lav sådan en her, hvor du sorterer på to felter, nemlig først på Y og så på to_char af a,b,... eller j.
SELECT * FROM Z ORDER BY Y, CASE Y WHEN 'a' THEN A WHEN 'b' THEN B WHEN 'c' THEN C WHEN 'd' THEN TO_CHAR(d) WHEN 'e' THEN TO_CHAR(e) WHEN 'f' THEN TO_CHAR(f) WHEN 'g' THEN TO_CHAR(g) WHEN 'h' THEN TO_CHAR(h) WHEN 'i' THEN TO_CHAR(i) WHEN 'j' THEN TO_CHAR(j) ELSE 'ÅÅÅÅÅ' END
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.