Avatar billede miqe Nybegynder
19. maj 2007 - 10:25 Der 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

Hvad skal jeg gøre?
Avatar billede miqe Nybegynder
19. maj 2007 - 10:29 #1
Er godt klar over at mit LOOP mangler i ovenstående udtryk ;-)
Avatar billede miqe Nybegynder
19. maj 2007 - 11:00 #2
Løste det ved at neste.

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.
Avatar billede kjulius Novice
19. maj 2007 - 12:09 #3
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)
Avatar billede miqe Nybegynder
19. maj 2007 - 12:17 #4
Hmm Muligvis har jeg givet et dårligt eksempel.

Glem concateneringen.
Jeg får også samme problem andre steder.
Det er når kollonerne har forskellige datatyper, jeg får problemet.

Virker til at CASE kun vil have én datatype ad gangen.
Avatar billede kjulius Novice
19. maj 2007 - 16:07 #5
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)

Er det bedre?
Avatar billede miqe Nybegynder
19. maj 2007 - 18:11 #6
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.
Avatar billede 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)
Avatar billede miqe Nybegynder
20. maj 2007 - 16:05 #8
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?
Avatar billede 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
Avatar billede miqe Nybegynder
29. maj 2007 - 22:16 #10
Det løste desværre ikke helt mit problem.
Har fundet ud af at man også kan bruge DECODE()


SELECT *
  FROM Z
ORDER BY DECODE(Y,
  'a',a,
  'b',TO_CHAR(b,'YYYYMMDD'), --DATE
  'c',c,
  'd',d,
  e        --DEFAULT
)

Joern_h, Du kom tættest på noget jeg kunne bruge, så jeg vil give dig en håndfuld points, selvom mit problem ikke blev helt løst.
Avatar billede miqe Nybegynder
29. maj 2007 - 22:16 #11
.
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