Zoektocht door de tijd
SQL is sterk verbonden met het relationele model van wijlen Edgar Codd.
Deze legendarische Britse wetenschapper publiceerde in 1969 al een
artikel onder de titel "A Relational Model of Data for Large Shared
Data Banks" [1] waarin de theoretische basis werd gelegd voor de
relationele databases van vandaag de dag.
SQL is primair nog steeds een querytaal. Er zullen maar weinig IT-ers fronsen bij de aanblik van een statement als
SELECT *
FROM Medewerker
WHERE Salaris > 10.000
ORDER BY Geboortedatum;
Het
relationele model is gebaseerd op tabellen, zoals de tabel “Medewerker”
in het bovenstaande voorbeeld, en de relaties tussen tabellen,
bijvoorbeeld tussen “Medewerker” en “Afdeling”. De tabellen
representeren de entiteiten die
in een bepaald probleemdomein relevant zijn. Een bedrijf heeft
vestigingen en vestigingen hebben medewerkers. De relatie tussen een
medewerker en een vestiging noemen we in het dagelijks leven een
dienstverband. Zo'n dienstverband kun je als een aparte entiteit
modelleren. Helaas is er niet voor alle relaties tussen entiteiten een
ingeburgerd begrip voorhanden. Het is dan ook niet echt gebruikelijk om
zulke relaties als een entiteit te onderkennen.
Integrity Constraints zijn
formele regels die erop gericht zijn om de consistentie tussen data in
verschillende tabellen te bewaken. Stel dat een vestiging wordt
gesloten; dan ligt het voor de hand dat er ook geen medewerkers meer in
dienst zijn bij die betreffende vestiging. Met een constraint
kun je voorkomen dat er medewerkers in de database voorkomen die een
relatie (i.c. dienstverband) hebben met een vestiging die niet meer
bestaat. Net zo goed kun je met zo'n constraint
bewaken dat een valuta, bijvoorbeeld de gulden, niet verwijderd mag
worden zolang er nog facturen in de database voorkomen die in guldens
zijn opgesteld.
Tot
zover gesneden koek. Appeltje eitje. Kind kan de was doen. Toch meen ik
een fundamentele beperking in het relationele model op het spoor te
zijn. En nog wel eentje die in heel veel systemen tot nodeloze
complexiteit leidt of tot een vervelende beperking van de
functionaliteit.
Wat
mij namelijk al vele jaren verbaast is het ontbreken van het concept
van tijdgebonden relaties in het relationele model – en vooral het
gebrek aan discussie daarover. Het lijkt een impliciete aanname dat
relaties tussen entiteiten altijd vast zijn. Toch zie ik in de praktijk
heel veel relaties die je eerder vloeibaar zou kunnen noemen. Een paar
voorbeelden.
-
Een bedrijf heeft gedurende een bepaalde periode een zekere vestiging
-
Een medewerker heeft gedurende een bepaalde periode een dienstverband met een vestiging van een bedrijf
-
Een medewerker heeft gedurende een bepaalde periode een bepaald salaris
En als je je er eenmaal bewust van bent, dan zie je ineens overal dit soort tijdgebonden relaties.
-
Een artikel heeft gedurende een bepaalde periode een prijs
-
Een artikel heeft ook gedurende een bepaalde periode een leverancier
-
Een artikel is gedurende een bepaalde periode in een assortimentsgroep ingedeeld.
Iedereen die wel eens te maken heeft gehad met het fenomeen terugwerkende kracht, of juist vooruitwerkende kracht,
zal hoogstwaarschijnlijk tegen soortgelijke relaties zijn aangelopen.
Wellicht dat hij of zij zich nog herinnert dat het best lastig is om
dit soort relaties goed te modelleren. Ik ken zelfs mensen die spontaan
in de stress schieten bij het horen van het woord peildatum.
Nu
is het op zich binnen het relationele model best te doen om een relatie
tussen twee entiteiten tijdgebonden te maken. Wat je kunt doen is – in
plaats van een enkelvoudige relatie tussen twee entiteiten – een
driehoeksrelatie modelleren, waarbij in één entiteit de tijdvakken
vastliggen die voor de relatie tussen de twee andere entiteiten gelden.
Dus zoiets als in bijgaande afbeelding.
Er
zit wel een klein nadeel aan zo'n constructie. Eenvoudige queries
vertalen zich in SQL al snel in een behoorlijk ingewikkelde syntax met joins tussen de tabellen en conditionele where-clauses
om af te testen of de begindatum van het dienstverband wel in het
verleden ligt en de einddatum van het dienstverband ofwel nog niet is
ingevuld, ofwel tenminste in de toekomst ligt. En gaat het nog maar om
de simpele vraag naar een lijst met medewerkers per vestiging op een
bepaald moment in de tijd. Zodra het iets ingewikkelder wordt,
bijvoorbeeld de leverancier van een artikel (tijdvak 1) in een
assortimentsgroep (tijdvak 2) per filiaal (tijdvak 3) op een bepaald
moment in de tijd, dan heb je al te maken met drie verschillende
tijdvakken, en evenzovele relatie-entiteiten, en explodeert een SQL
query al snel tot tot een lengte die niet meer op een A4-tje past.
Zou
het nou niet mogelijk zijn om SQL net iets slimmer te maken, om dit
soort veel voorkomende relaties beter te ondersteunen? Zou het concept
van tijdsnuggere relaties eigenlijk geen pijler onder het relationele model moeten zijn?
Om over te peinzen
Het
is niet zo moeilijk om te bedenken hoe een tijdsnuggere SQL query er
ongeveer uit zou moeten zien. Je zou al een eind in de richting kunnen
komen met
SELECT *
FROM Medewerker
ON Datum
WHERE Salaris > 10.000
ORDER BY Geboortedatum;
Het
is ook niet zo moeilijk om je voor te stellen dat een query
preprocessor zo'n query automatisch zou kunnen expanderen naar een
geldige SQL query met bijbehorende where clauses. En als we dan
toch bezig zijn, dan weet ik er nog wel een paar. Neem nou de lijst met
medewerkers uit het afgelopen jaar per filiaal
SELECT Medewerker.naam
FROM Filiaal, Medewerker
DURING (20070801; 20080731)
GROUP BY Filiaal;*
Het
kan toch niet zo moeilijk zijn om uit een dergelijke syntax eenduidig
de conclusie te trekken dat het alleen om medewerkers gaat die in de
opgegeven periode voor een filiaal hebben gewerkt? Of neem de lijst met
omzet per maand van alle filialen die gedurende de gehele afgelopen 12
maanden omzet hebben gemaakt – de zogenaamde vergelijkbare omzet.
SELECT SUM (Omzet.bedrag)
FROM Filiaal, Omzet
DURING ALL (20070801; 20080731)
WHERE Omzet.datum >= 20070801
AND Omzet.datum <>*
Deze
is al een stukje lastiger te verwerken, omdat “ergens” de kennis vast
moet liggen dat de during clause in dit geval ziet op het tijdvak dat
het filiaal binnen het bedrijf actief was – dus iets betekent als
WHERE Filiaal.Startdatum <= 20070801 AND ( Filiaal.Einddatum >= 20080731
OR Filiaal.Einddatum = NULL)
En
omdat dit nog relatief simpele voorbeelden zijn, zal het nog best het
nodige denkwerk vereisen om een syntax te bedenken die in alle gevallen
werkt. Toch ben ik er heilig van overtuigd dat er voor dit soort
logische relaties ook een logische notatie te bedenken moet zijn. En
dat het tijdvakconcept tot een standaard construct in relationele
databases kan worden verheven. Het is wat mij betreft de hoogste tijd
dat daar eens een degelijk proefschrift aan wordt gewijd.
Trouwens,
als je er even over piekert, dan valt er op dit gebied nog veel meer te
automatiseren. Stel je voert in dat een medewerker vanaf 1 januari een
hoger salaris krijgt. Een slimme computer zou dan begrijpen dat dit
automatisch betekent dat het lopende salaristijdvak moet worden
afgesloten op 31 december – dit soort salarissen sluiten elkaar immers
uit. Op dezelfde manier zou je kunnen bedenken dat als een medewerker
benoemd wordt tot productmanager van een productgroep, deze rol voor de
huidige medewerker ophoudt. Of als een artikel vanaf een bepaalde datum
in een bepaalde assortimentsgroep valt, het niet meer in de huidige
groep thuishoort. Ik zie dus veel potentie voor een automatisch
gegenereerde tijdvakconstraint.
Zo'n automatisme geldt overigens niet voor alle relaties – niet alle relaties zijn mutually exclusive.
Eén artikel kan op één moment in de tijd misschien best meerdere
leveranciers hebben, net zo goed als één medewerker op één moment in de
tijd best voor twee verschillende afdelingen kan werken. Aan de andere
kant, een filiaal waar de laatste medewerker uit dienst gaat kan
hoogstwaarschijnlijk gesloten worden, net zo goed als een artikel dat
zijn laatste leverancier verliest best uit het assortiment genomen kan
worden (of vice versa) en zo goed als voor een assortimentsgroep die
wordt afgesloten alle tijdvakken van artikelen die aan die groep zijn
gekoppeld best automatisch beëindigd zouden kunnen worden. In deze
laatste gevallen zie ik nog een ander patroon, namelijk dat van de
subperiode. Je kunt een algemene regel bedenken dat de periode van een
dienstverband altijd moet vallen binnen de periode dat het
organisatieonderdeel waarmee het wordt aangegaan bestaat. Of dat een
prijs van een artikel alleen maar loopt binnen het tijdvak dat een
artikel in het assortiment zit. Ook dergelijke tijdvakconstraints, die bij een UPDATE of een INSERT het leven aanzienlijk zouden kunnen vergemakkelijken, zouden
relatief eenvoudig uit een tijdsnugger datamodel te genereren kunnen
zijn. Maar dan moet er ook nog wel even een tijdsnuggere modelleertaal
bedacht worden...
Mocht je door dit pleidooi geïnspireerd zijn geraakt, dan weet ik alvast een prikkelende stelling voor je proefschrift.
Het is de hoogste tijd dat de tijd dat SQL de tijd niet in de gaten had tot de verleden tijd gaat behoren.
Hora est.
Deze overpeinzing is bedoeld om tot nadenken te stemmen. Het is de 8ste in een reeks bespiegelingen.
Deze is op 7 augustus 2008 gepubliceerd op ArchITectuur
Bedrijven.
* Deze voorbeelden zijn bewust gesimplificeerd.
[1] Codd, E.F: "A Relational Model of Data for Large Shared Data Banks"; Communications of the ACM 13 (6): 377–387, 1970.
Only registered users can write comments. Please login or register. |