Avatar billede md_craig Nybegynder
13. december 2007 - 08:54 Der er 5 kommentarer og
1 løsning

rekursiv SQL og joins

Hej...

Jeg har en situation hvor jeg evt. kan bruge noget rekursivt SQL, har læst lidt om at det skulle kunne gøres, men de eksempler jeg har fundet er med en tabel der har en row der heder parrent. så det er lidt for enkelt i forhold til min situation.

Jeg har teknisk set 3 tabeller, kan måske undlade det 3. men det er lidt usikkert nu.

Jeg har nogle Objecter, objeckterne selv er lagret i en tabel med informationer om hvor det hører hjemme i en fil/mappe lignende struktur lad os kalde den tabel "O" for objekt.

Da man ikke direkte kan arbejde på objekter, tager man en kobi før dette gøres, når man har arbejdet færdig smider man så den kopi ind istedet for den originale, men da deres unikke ID bliver exponeret i nogle views til en aprtner, har vi brug for at bibeholde samme id, det er løst ved at have en tabel til at styre dette som Referere objecter ved et overordnet id, den tabel kalder vi "I" for identitet.

Sidst kan objekter arrangeres i et træ, det gøres ved en hjælpetabel der "kæder" dem sammen, tabellen har lidt yderligere informationer om relasionen som hvornår den blev lavet osv, derfor en tabel seperat til det, lad os kalde den sidste tabel "R" for relasion.

Så vi har:
"O" : objekter
"I" : identitet
"R" : relasion

I indeholder 2 ting. en unik Identitet og en FK til O id... så:
"I" ("I.id", "I.oid")

O har naturligvis et ID og så et tilhørsforhold (mappe id)
"O" ("O.oid", "O.mid")

R har så en parrent ("O/I.oid") og en child ("I.id")
"R" ("R.oid", "R.id")

Ok... jeg har prøvet at holde tingene så simple som muligt i forhold til hvad jeg har brug for, lidt en lang historie men håber det går, og at det ikke skræmmer folk væk.

Nu vil jeg så gerne have et flat view at alle objekter i en træstruktur ud fra et specifikt objekt id... og det tænkte jeg at jeg kunne bruge det her rekursive SQL til...

Tabellen "O" kan måske undlades, ved ikke helt om jeg får brug for at udvælge noget i den ud fra "O.mid", derfor er den lige med... Joins kommer jo så ind da det er "R" der linker objekter sammen.
Avatar billede steber Nybegynder
14. december 2007 - 06:21 #1
Hej,
1) Hvis du har en "normal" tabel kan du bruge CONNECT BY PRIOR syntaksen i en normal SQL SELECT for at traversere og vise indholdet i en tabel i en træstruktur. Nu har du flere tabeller og ikke mindst objekter. Det er mange år siden jeg har brugt syntaksen selv, men jeg vil tro at du ikke kan bruge det p.g.a. dine objekter. Søg på CONNECT BY i SQL dokumentationen.
2) Du kan lave en PL/SQL TABLE FUNCTION hvor du selv looper etc. igennem data som du vil og returnerer én række af gangen i det format du vil. Denne TABLE FUNCTION kan du så bruge fra e.g. et view eller et SELECT statement. Søg i PL/SQL dokumentationen (eller google) efter TABLE FUNCTION eller PIPELINED.
Avatar billede md_craig Nybegynder
14. december 2007 - 10:24 #2
Det er netop Connect By Prior jeg har kigget på og som jeg gerne vil bruge, men som sagt så har jeg kun fundet single table eksempler.

Det eneste hint jeg har fundet på om det kan lade sig gøre over flere tables er:
http://technology.amis.nl/blog/?p=718

Hvor det jeg har fået ud af den side so far er, at det kan det. Så smed et spørgsmål her mens jeg grublede videre selv...
Avatar billede md_craig Nybegynder
14. december 2007 - 10:55 #3
WITH nodes AS
  (  SELECT I.id AS i_id, I.oid AS i_oid, R.oid AS parrent, R.id AS child_id
      FROM I LEFT OUTER JOIN R ON I.oid = R.oid  )
SELECT i_id, i_oid, parrent, child_idFROM nodes
  CONNECT BY PRIOR i_id = child_id
  START WITH child_id IS NULL;

Så langt så godt, overstående spytter da et eller andet ud, om det er korrekt er jeg lidt langt fra at kunne se, desuden så skal der stadig kreterier ind... dog tror jeg at jeg fik fat i essensen af det han havde gang i.
Avatar billede md_craig Nybegynder
14. december 2007 - 16:40 #4
Ok det endte med at blive strikket sammen til:

WITH nodes as
  (  SELECT I.id as i_id, I.oid as i_oid,
            O.name as name, O.mid as mid,
            R.oid as r_oid, R.id as child_id
      FROM I
      INNER JOIN O ON O.oid = I.oid
      LEFT OUTER JOIN FITS ON I.oid = R.oid
      )
SELECT UNIQUE i_id, i_oid, name, mid FROM nodes
  START WITH i_id = 1 --(Indsæt Kriterie id)
  CONNECT BY PRIOR child_id = i_id;

Og det ser ud til at virke... (Puha)...
Er ikke helt med på hvorfor eksempler der ude ikke benytter Unique mens jeg til syneladende har brug for det for ikke at få dupeletter, men der er måske noget grouping eller andet jeg har overset...

Men so far så ser det ud til at give et korrekt resultat...
Avatar billede md_craig Nybegynder
27. december 2007 - 13:20 #5
Nå ja... fik da SQL'en til at virke efter ønske i sidste ende...

Næste problem er at OracleClient ser ud til at hoste op over den Query... så kom da kun til det næste problem... men lukker her da SQL i det mindste er på plads (også på flere afprøvede måder nu)...

Så hvis du lige ligger et svar så får du lige lidt af points, da jeg...

a. Må indrømme at jeg stadig slet ikke har afprøvet, eller overvejet at kigge på (2).
b. Og at (1) jo var lidt hen af det rigtige (selv om jeg jo godt viste det på daværende tidspunkt, men stod der jo ikke lige frem nogen steder i spørgsmålet...
Avatar billede md_craig Nybegynder
08. februar 2008 - 12:30 #6
na men så nupper jeg selv det hele :)
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