Avatar billede kavlar Novice
30. marts 2017 - 17:39 Der er 10 kommentarer og
1 løsning

Rekursiv SQL Query

Jeg arbejder på en DB2 database, hvor varetekster er gemt på flere linjer. Tabellen er opbygget sådan, at der for hvert varenummer er x-antal rækker der dækker varebeskrivelsen:

Varenummer | Linjenummer | TEKST
123 | 1 | Beskrivelse af varen linje 1
123 | 2 | Beskrivelse af varen linje 2
123 | 3 | Beskrivelse af varen linje 3
123 | 4 | Beskrivelse af varen linje 4
123 | 5 | Beskrivelse af varen linje 5

Min udfordring er, at nogle varebeskrivelser er skrevet på eks. 5 linjer, mens andre er skrevet på eks. 23 linjer.

Jeg har tidligere arbejdet med left outer join og joinet tabellen på sig selv 23 gange.

Eks:

SELECT *
FROM TABEL as a1
LEFT OUTER JOIN TABEL as a2 ON a1.Varenummer  = a2.varenummer and a2.Linjenummer  = 2
LEFT OUTER JOIN TABEL as a3 ON a1.Varenummer  = a3.varenummer and a3.Linjenummer  = 3
...
LEFT OUTER JOIN TABEL as a2 ON a1.Varenummer  = a22.varenummer and a22.Linjenummer  = 22
LEFT OUTER JOIN TABEL as a2 ON a1.Varenummer  = a23.varenummer and a23.Linjenummer  = 23
WHERE a1.Linjenummer  =1

Men jeg tænker der må være en smartere måde at gøre det på, hvor man laver et eller andet loop der kører det antal gange der er linjer for den enkelte vare. Min udfordring er nemlig, at der er intet til hindring for at der på et tidspunkt tastes 100 linjer eller 10000 linjer.
Avatar billede arne_v Ekspert
30. marts 2017 - 18:08 #1
Kan du ikke flytte logikken fra SQL til applikation?
Avatar billede kavlar Novice
30. marts 2017 - 20:49 #2
Tak for respons. Desværre er udfordringen her, at jeg ofte skal bruge dataene i forbindelse med analyser og derfor godt kunne bruge, at der var en standard kørsel, der samler teksterne i én række i stedet for x-antal rækker, alt efter hvor mange kolonner der er. Næste udfordring bliver selvfølgelig at finde ud af, hvor mange kolonner jeg har, men det kan evt. løses i applikationen. Jeg har i hvert fald ikke rigtig fantasi til at udtænke hvordan jeg ellers løser det.
Avatar billede acore Ekspert
30. marts 2017 - 21:12 #3
Måske du kan bruge GROUP_CONCAT?

SELECT Varenummer, GROUP_CONCAT(Tekst ORDER BY Linjenummer SEPARATOR ' ')
FROM Tabel
GROUP BY Varenummer

(ikke testet)

Der er muligvis en begrænsning på max-længden, som du først skal justere med fx

SET group_concat_max_len = 2048
Avatar billede acore Ekspert
30. marts 2017 - 22:21 #4
Tror det var et dårligt råd jeg gav, for der er ikke GROUP_CONCAT i DB2.

Men fandt http://www.vertabelo.com/blog/technical-articles/group-concat som jeg ikke har prøvet da jeg ikke har DB2 kørende.
Avatar billede arne_v Ekspert
31. marts 2017 - 01:52 #5
GROUP_CONCAT er MySQL specifik.
Avatar billede arne_v Ekspert
31. marts 2017 - 01:53 #6
Den paeneste loesning ville nok vaere at lave en SP eller UDF i Java som hentede data og returnerede dem som du vil have det.

Har du adgang til at lave SP/UDF?
Avatar billede acore Ekspert
31. marts 2017 - 10:32 #7
Ifølge linket i #4 er der måske en  LISTAGG(colname, separator) funktion i DB2.

Du kunne da prøve...
Avatar billede kavlar Novice
31. marts 2017 - 11:04 #8
Tusind tak for jeres input. Jeg fandt en løsning der virkede fra linket.
Avatar billede acore Ekspert
31. marts 2017 - 11:17 #9
Bare af interesse - hvad endte det med - overordnet?
Avatar billede kavlar Novice
05. april 2017 - 10:03 #10
Hej alle

Det blev til følgende:

WITH
    TABEL_numbered(rowNum, Varenummer, tekst) AS
    (
      SELECT Linjenummer,
      Varenummer, Tekst
      FROM (SELECT Linjenummer, Varenummer, TRIM(tekst) AS tekst
        FROM TABEL
    ),
    TABEL_grouped (Varenummer, list, idx) AS
    (
      SELECT Varenummer, Tekst, 1
      FROM TABEL_numbered
      WHERE rowNum = 1
      UNION ALL
      SELECT
      TABEL_grouped.Varenummer,
      CAST(TABEL_grouped.list  || chr(10) || TABEL_numbered.Tekst as CLOB),
      TABEL_grouped.idx + 1
      FROM TABEL_grouped, TABEL_numbered
      WHERE
      TABEL_grouped.Varenummer = TABEL_numbered.Varenummer
      AND TABEL_grouped.idx + 1 = TABEL_numbered.rowNum
    )
SELECT Varenummer, list
FROM TABEL_grouped
WHERE ( Varenummer, idx ) IN (
    SELECT Varenummer, MAX(rowNum)
    FROM TABEL_numbered
    GROUP BY Varenummer )
ORDER BY 1
Avatar billede acore Ekspert
05. april 2017 - 10:15 #11
Tak for info - det endte som en lærerig tråd for mig :)
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

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