loop in query

Status
Niet open voor verdere reacties.

basstaffort

Nieuwe gebruiker
Lid geworden
11 jan 2015
Berichten
4
Beste helpmij guru's,

Ik heb een query nodig die alle boeken die opeenvolgend zijn weet te vinden.

De tabel heeft 2 belangrijke velden:

  • BoekID
  • Vorig_boek

In vorig_boek staat het ID van een ander boek.
Als we als voorbeeld de harry potter reeks pakken dan ziet dat er als volgt uit:

1
2 1
3 2
4 3
5 4

Dit wil zeggen dat boek 3 de voorloper is van boek 4.

Nu wil ik dus een query waarbij ik als het waren vraag "als ik boek 4 heb, welke boeken hebben daar dan mee te maken?"

Oftewel dan zou ik boek 1 t/m 5 uit de harry potter serie als resultaat willen hebben.

Het was me middels een subquery al gelukt 2 boeken ver te zoeken maar dan zou ik voor alle series een aparte query moeten maken.

Wie o wie kan me helpen?
 
Hoezo?

Als ik een database had met boeken,
dan zou ik daarin een paar tabellen opnemen
- schrijvers
- boeken (velden o.a.: titel, hoofdpersoon, jaar van uitgave)
- uitgevers
- genre

Ik zou me niet zo gouw een situatie kunnen voorstellen waarbij ik zoiets als een [vorig_boek_id] nodig zou hebben.
Waarschijnlijk zouden de titels en/of uitgavejaar me kunnen helpen om een bepaalde volgorde te tonen.
 
Als je een volgorde gaat vastleggen op de door jou voorgestelde manier,
kun je in de problemen raken als je op enig moment iets moet tussenvoegen.
 
Er zit meer in de database, dat doet er alleen niet toe.

Een boekvolgorde veranderd niet. Als harry potter 3 verdergaat op harry potter 2 kan die daarna nooit meer verdergaan op harry potter 6.
Wat hooguit kan gebeuren is dat harry potter 6 OOK van harry potter 2 is verdergegaan.
Dan krijg je:

1
2 1
3 2
4 3
5 4
6 2

Het is dus geen volgorde :) Vorig_boek geeft slechts aan op welk boek dit boek een vervolg is. (of een afleidend stuk zoals een vertaling)
 
Ik neem aan dat het niet alleen om 7 Harrie Potter boeken gaat.

Het is meestal een misvatting om te denken dat "de rest van de database" er niet toe doet.
Daar kunnen best gegevens in zitten die deel van de oplossing kunnen zijn.

Ook de omvang van de database kan bepalend zijn voor je probleem en voor je oplossing.
Als je hier een oplossing zoekt voor een bestand van honderd boeken die je zelf allemaal hebt gelezen en kent
zou ik zeggen "veel plezier, ga vooral je gang en ik hoop datr iemand een opolossing voor je heeft".l
Maar als het hier gaat om een oplossing voor een complete bibliotheek van pakweg enkele duizenden boeken
of om een hele zooi boeken die je niet zelf inhoudlijk allemaal kent,
dan ben je op de verkeerde weg.
Dan kun je wat goede raad gebruiken.


De situatie dat in een hele reeks boeken een inhoudelijke volgorde anders is dan de volgorde waarin de boeken worden uitgegeven ligt niet voor de hand.
Dat betekent dat jaar van uitgave (eventueel meerdere maanden in een jaar) een hele goede manier is om volgorde vast te stellen.

Met tussenvoegen bedoel ik het volgende:
Stel je hebt een lange reeks boeken van één schrijver.
Alle boeken bevatten afgeronde verhalen, maar in de persoonlijke omstandigheden van de hoofdperso(o)n(en) zit wel een ontwikkeling
(relaties die beginnen en aflopen, kinderen die ouder worden, carrières).
Stel dat je een reeks boeken hebt ingevoerd; je denkt dat je ze allemaal hebt. Dan blijkt plotseling dat er toch nog een boek bestaat dat je over het hoofd hebt gezien.
Dan moet je dus ergens je volgorde-code gaan onderbreken en een nieuwe tussenvoegen.

Het is een extra gegeven waarvan ik de praktische waarde in twijfel trek.
 
Als je series wilt vastleggen, dan moet je een serie als een aparte entiteit beschouwen. Een reeks is dan namelijk altijd een verzameling, die bestaat uit een aantal boeken. En dat is iets anders als een boek. In die aparte tabel neem je dan de naam van de serie op (Harry Potter, James Bond etc). Elk boek dat in de serie valt, krijgt dan een record met een koppelingstabel Boek_Serie waarin dus het serieID en het BoekID wordt opgeslagen. Dan kun je ook eindeloos doorbreien zonder dat de geneste tabellen, zoals je het nu doet, in de knel komen.
 
Maar dit moet toch kunnen met SQL?

Zeg dat het muziekstukken zijn, dan heb je toch ook geen series? Als ik wil weten welke stukken allen van nummer 2 zijn afgeleid of van een afgeleid stuk is afgeleid dan zal het toch ook op deze manier moeten?
 
Maar dit moet toch kunnen met SQL?
Nee.

Ik heb een query nodig die alle boeken die opeenvolgend zijn weet te vinden.
Hoe weet je hoe vaak een loop moet worden doorlopen? De ene serie heeft 7 boeken (Potter) en de andere serie maar 3 (Lord of the Rings). En dan hebben we het nog niet over series als James Bond... Kortom: dat gaat nooit lukken met een lus in een query. Je moet dan namelijk voor elke tak een nieuwe kopie van de tabel toevoegen die je koppelt aan de vorige.
Hetzelfde principe heb je in een genealogie database, waar je een persoon toevoegt, en daar vervolgens de kinderen van toevoegt. Die hebben als vader dan het eerder toegevoegde record, en als moeder ook een ouder record. Dus in het veld V_ParentID vul je de vaderID in en in M_ParentID de moeder. Die personen hebben zelf uiteraard ook weer ouders, en als je die toevoegt aan de db kun je daarvoor ook een ParentID toevoegen. En zo voort. Wil je een familieoverzicht in een query, dan moet je van tevoren bepalen hoeveel generaties je wilt zien, want zoveel keer moet je de tabel toevoegen, en zoveel keer moet je ook de tabellen koppelen aan de respectievelijke ParentID's.

En nog een voorbeeldje: een tabel met categorieën en subcategorieën. Een onderwerp dat in dit forum nog wel eens voorbij komt. Daar worden vaak aparte tabellen voor gemaakt, maar dat vind ik niet echt handig, omdat je voor elke verdere onderverdeling weer een aparte tabel nodig hebt. Dan blijf je bezig met aanpassen. In dat geval gebruik ik één tabel, met een verwijzing naar een hogere categorie. Dus de tabel heeft een extra veld ParentID. Het hoogste niveau dat je in deze tabel vastlegt, de Hoofdcategorie dus, heeft, omdat het nu eenmaal het hoogste niveau is, geen waarden in de ParentID. En die kun je er dus makkelijk uitfilteren. Verder is het een kwestie van net zoveel klonen opnemen van de Categorie tabel als er niveau's zijn, zodat je alle subcategorieën correct kunt doorfilteren.
Een vergelijkbaar voorbeeldje heb je als je een bedrijfsprofiel gaat analyseren. Daar kun je een organisatiestructuur makkelijk maken door te beginnen bij de Directeur (hoogste niveau) en daaronder een laag managers die als ParentID gelinkt (verantwoording afdragen aan) de directeur, daar weer een groep mensen onder (teamleiders) die zijn gelinkt aan de manager, en daar weer personen onder die zijn gelinkt aan de teamleider.

Wat is er nu anders aan mijn voorbeeldje t.o.v. jouw vraag? Want je zou nu kunnen denken dat ik wel degelijk dezelfde oplossing gebruik als die jij zoekt. Het belangrijkste verschil: in mijn voorbeelden zijn de entiteiten identiek. Een categorie is in essentie hetzelfde als een subcategorie, en als een subsubcategorie. Een familielid is per definitie een persoon, en dus als object identiek als ouder of kind. En een werknemer is als object altijd een werknemer. Een reeks boeken is echter een verzameling, en bestaat derhalve altijd uit meerdere niet van te voren bepaalde leden. En een boek is weer een altijd zelfstandige entiteit. Een boek is dus absoluut niet hetzelfde als een verzameling. En moet daarom anders worden behandeld.

Dus als je van tevoren niet weet hoeveel boeken er gelinked zijn, dan heb je een groot probleem. Je kunt dan ervoor kiezen om dan maar een stevig aantal klonen van de tabel toe te voegen, en je suf te linken, zodat de kans groot is dat je de meeste series wel hebt afgevangen, maar dat is niet echt een wetenschappelijke benadering.
Of je kiest voor mijn oplossing, die a) veel makkelijker is en b) geen beperkingen kent in het gebruik omdat die altijd het gewenste resultaat oplevert.

Er is nog een (lastig) alternatief, en dat is dat je alles oplost met programmeren, dus met VBA. Daarin kun je wél een lus maken op basis van een bepaald gegeven. Maar dat moet je dus helemaal niet willen....
 
Als het een standaard "linked list" probleem zou zijn is er niet zo'n probleem. Het programmatisch oplossen van een linked list is een standaard opgave. Maar zoals de anderen aangeven is het antwoord wat je zoekt niet te voldoen.
Nu wil ik dus een query waarbij ik als het waren vraag "als ik boek 4 heb, welke boeken hebben daar dan mee te maken?"

Oftewel dan zou ik boek 1 t/m 5 uit de harry potter serie als resultaat willen hebben.

Je kunt vanuit boek 4 met een linked list wel 1,2,3 vinden (ook met SQL overigens http://msdn.microsoft.com/en-us/library/ms175972.aspx ). Wat je echter NIET kunt vinden is boek 5. Wat je daar probeert te doen is ook een "forward reference lookup" en dat is per definitie een complexe opdracht.

Zoals de anderen ook al aangeven zie ik echter niet in waarom je geen "dit is onderdeel van serie xyz" reference maakt.
 
@wampier: We hebben het hier over Access, en niet over SQL server. Staat al in de derde regel van het verhaal aangegeven:
Applies to: SQL Server (SQL Server 2008 through current version), Azure SQL Database.
Dus hier niet van toepassing.
 
Klopt, maar je geeft aan dat het niet met SQL kan in je antwoord... Meer specifiek is dat dus afhankelijk van je engine. SQL (de taal) heeft dus een provisie voor dergelijke problemen (en recursie). Access toevallig niet.

Maar gezien geen enkele (table based) database een standaard oplossing heeft voor forward lookups ontkom je eigenlijk niet aan programmeren.
 
We hebben het hier over een Access forum, en zolang TS zelf niet aangeeft dat hij met een SQL server als backend werkt, zal ik in de antwoorden die ik geef geen zijsporen aanbieden die toch niet werken. Wat heeft TS er aan dat het in een andere database wel kan?
 
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan