[SQL] dynamische JOINS? *

Pagina: 1
Acties:

  • Genoil
  • Registratie: Maart 2000
  • Laatst online: 12-11-2023
Voor een soort on-line pagina-editor gebruik ik een hierarchische database -structuur (adjacent model). De hierarchie ligt besloten in twee tabellen, node en relation (dat kennen we onderhand wel neem ik aan). node heeft daarnaast een veld 'class', die verwijst naar een andere tabel met daarin de voor die node specifieke gegevens. Je zou dus kunnen zeggen dat het een soort polymorfische boomstructuur is. Het is voor het doel van de pagina-editor misschien niet de meest handige oplossing, maar aangezien deze structuur alomtegenwoordig is in de rest van de webapplicatie waar de pagina-editor een onderdeeltje van is, heb ik deze ook hier gebruikt.

Nu bestaat elke 'page'-node uit een x-aantal 'block'-nodes. De 'block' node bevat o.a informatie over de positionering van zijn child-nodes op de 'page', is ahw een soort 'container'. De child nodes kunnen echter van verschillende classes zijn, 'paragraph', 'image', 'data source' etc.

Nu probeer ik in 1 query alle benodigde informatie uit de database te trekken voor het opmaken van zo'n pagina. Bestaat een pagina slechts uit 'paragraphs' dan valt het nog wel mee:

code:
1
2
3
4
5
6
SELECT node. * , block.*, paragraph.*
FROM relation AS r1, relation AS r2
JOIN node ON node.id = r1.child_id
JOIN block ON block.node_id = node.id
JOIN paragraph ON paragraph.node_id = r2.child_id AND r2.parent_id = r1.child_id
WHERE r1.parent_id = 21


Maar aangezien een block meerdere typen objecten kan bevatten, kan ik m'n query oneindig uit gaan breiden met JOINS voor elke class. Dus vroeg ik mea f of er niet een mechanisme bestaat waarmee je dynamisch tabelnamen kunt genereren op basis van tussenresulaten. Zoiets als dit (PSEUDOCODE!!!):

code:
1
2
3
4
5
6
7
SELECT b-node.*,  c-node.*, block.*, child.*
FROM relation AS r1, relation AS r2
JOIN node AS b-node ON b-node.id = r1.child_id
JOIN block ON block.node_id = b-node.id
JOIN node AS c-node ON c-node.id = r2.child_id AND r2.parent_id = r1.child_id
JOIN {c-node.class} AS child ON child.node_id = c-node.id  
WHERE r1.parent_id = 21


Wat ie dus zou moeten doen is alle tabellen joinen die dezelfde naam hebben als het class veld van c-node...

Dit kan vast niet he....

[ Voor 14% gewijzigd door Genoil op 28-04-2003 16:09 ]


  • Annie
  • Registratie: Juni 1999
  • Laatst online: 25-11-2021

Annie

amateur megalomaan

Genoil schreef op 28 april 2003 @ 16:01:
Dit kan vast niet he....
Uh, nee, in ieder geval niet in deze vorm.

Wat vaak wel kan (afhankelijk van de database die gebruikt wordt) is het dynamisch samenstellen van queries binnen stored procedures. Maar of je daar helemaal gelukkig van moet worden? Ik zie het meestal liever als een allerlaatste redmiddel.

Wat misschien ook kan is tussenresultaten opslaan in tijdelijke tables en deze aan het einde teruggeven in 1 recordset. Of met een creatief gebruik van outer-joins alle gegevens uitlezen en voor "niet aanwezige" data NULL's teruggeven.

Ik kan echter niet echt vat krijgen op je probleem (lange dag :O), dus echt veel zal je hier wel niet mee opschieten ;) Misschien is het hoofd morgen weer wat helderder.

Today's subliminal thought is:


Verwijderd

Uitgaan van stored procedures kun je wel case statements gebruiken :)

  • kvdveer
  • Registratie: November 2000
  • Laatst online: 06-11-2025

kvdveer

Z.O.Z.

Jij wilt OO-functionaliteit uit een gewone RDBMS trekken? Dat gaat je niet echt lukken denk ik.

Localhost, sweet localhost


  • Genoil
  • Registratie: Maart 2000
  • Laatst online: 12-11-2023
Ok jammer ik leg me er bij neer :)...het project waarvoor ik dit moet doen loopt toch al ten einde (baaad design decisions...) en het aantal verschillende soorten objecten binnen een pagina gaat toch beperkt blijven. Dus dan maar met de botte bijl:

code:
1
2
3
4
5
6
7
8
9
SELECT blocknode.name, block.rank, paragraph.body, image.url
FROM relation AS r1, relation AS r2
JOIN node AS blocknode ON blocknode.id = r1.child_id
JOIN node AS childnode ON childnode.id = r2.child_id AND r2.parent_id = r1.child_id
JOIN block ON block.node_id = blocknode.id
LEFT JOIN paragraph ON paragraph.node_id = childnode.id
LEFT JOIN image ON image.node_id = childnode.id
WHERE r1.parent_id = 21
ORDER BY block.rank


dus voor elk objecttype (zullen er straks 3 zijn, hooguit zo'n 5) een LEFT JOIN erbij en querien maar :)