Redundantie en normalisatie

Status
Niet open voor verdere reacties.

ArnoldL

Gebruiker
Lid geworden
31 okt 2011
Berichten
14
Beste forumleden,

ik ben me aan het verdiepen in het opzetten van een database voor een klein bedrijf.
In hetgeen ik hier al opgezocht en gelezen heb zie ik steeds terugkomen dat er tabellen voor klanten en tabellen voor leveranciers aangemaakt worden.

In mijn situatie zijn sommige klanten ook leverancier, en heb ik zowel bedrijven als particulieren als klant. Om hierin nog wat dieper te gaan, sommige bedrijven hebben een dienst voor aankoop, verkoop, facturatie, …, uitgevoerd door verschillend personeel, al kan 1 bepaalde persoon ook instaan voor meerdere eerder vermelde taken. Om het helemaal erg te maken kunnen verschillende diensten op verschillende adressen gevestigd zijn.

Nu mijn vraag. In verband met normalisatie en redundantie, is het dan niet wenselijk om een aantal aan elkaar gerelateerde tabellen te maken onder de overkoepelende naam “Relaties” en dan hieruit door middel van query’s de voor het dan beoogde doel nodige data te filteren? Of wordt het dan allemaal zeer moeilijk op te zetten, en gebruikt men daarom meestal verschillende tabellen voor klanten en leveranciers?

Alvast bedankt voor uw reactie.
 
Redundatie is niet meer dan het voorkomen van dubbele gegevens. In jouw geval is het duidelijk waar dat gaat plaatsvinden als je aparte tabellen maakt voor Klanten en Leveranciers: zodra een klant ook leverancier is, heb je dubbele records. En dat betekent bij mutaties dat je die ook 2 keer moet uitvoeren. Dat is uiteraard geen gewenste situatie.

Bij het opzetten van een database moet je in eerste instantie uitgaan van de gegevens die je gaat opslaan. Daarbij verdeel je die gegevens in bij elkaar horende objecten die we dan entiteiten noemen. Een persoon is daarbij een entiteit, en een artikel ook. Een persoon heeft andere eigenschappen (noemen we: attributen) dan een artikel. Een persoon die een klant is, heeft in principe dezelfde attributen als een persoon die leverancier is. Of een werknemer. Hij heeft een naam, een email adres, een woonadres en ga zo maar door. Regel één van normaliseren is dat je entiteiten die dezelfde attributen hebben bij elkaar zet in een tabel. Dat leidt er dus toe dat je personen bij elkaar zet in één tabel.
Dat levert een probleem op als het gaat om het onderscheid dat je tussen die personen wilt maken, want een persoon kan dus klant zijn of leverancier. Dat is simpel op te lossen met een extra veld waarin je de status aangeeft. Eventueel een extra tabel, of een veld met meerdere waarden. Dat laatste is database technisch minder handig als je wilt kunnen upgraden naar een hogere database zoals een SQL server, omdat dat soort databases alleen velden erkent waarin unieke waarden zijn opgeslagen. Het (redelijk nieuwe) veld met meervoudige waarden dat je tegenwoordig in Access hebt, slaat dat principe volledig omver, en daarmee ben je dus veroordeeld tot het gebruik van Access. Iets om in het achterhoofd te houden!

Zo'n personen tabel levert wel weer andere problemen op, want je hebt ook te maken met bedrijven. Een bedrijf is weer een eigen entiteit, en dient dus een eigen tabel te krijgen. Voor bedrijven geldt dan weer dat een bedrijf een adres heeft etc, gegevens dus die je ook in de personen tabel hebt opgeslagen. Dat zou er toe kunnen leiden dat je voor de adresgegevens een aparte tabel maakt. Of je volstaat met het invullen van postcode en huisnummer, waarna je op basis van een postcodetabel de adresgegevens ophaalt. Dat principe gebruik je dan natuurlijk ook in de personen tabel.

Daarnaast heeft een bedrijf kenmerken die niet voor een persoon opgaan, zoals: meerdere filialen en meerdere werknemers. Dat los je dan ook weer op met aparte tabellen waarin je de gegevens koppelt. Een filiaal is in beginsel niet veel anders dan een bedrijf, dus je kunt ook (mijn voorkeur) een filiaal ook als een bedrijf invoeren in de Bedrijven tabel met een verwijzing naar het bovenliggende filiaal. Daartoe volstaat een extra veld in de Bedrijven tabel waarin je dus onderscheid ziet tussen hoofdfilialen (die hebben géén waarde in het veld ParentID) en filialen, waarin je in het veld ParentID de waarde invult van het hoofdfiliaal. Met deze constructie kun je een filiaal óók nog eens dochterfilialen laten hebben, want die krijgen dan een verwijzing naar wat voor hun de ParentID is.

Werknemers van een bedrijf zet je in een koppeltabel waarin je dus een verwijzing opneemt naar het BedrijfID, en (werknemers zijn net mensen) een verwijzing naar het PersoonID uit de personentabel. Want we hebben al vastgesteld dat entiteiten die dezelfde atrributen hebben in één tabel komen te staan. Van een werknemer van een bedrijf heb je waarschijnlijk geen adresgegevens, maar die hoef je dan uiteraard niet in te vullen. Je kunt er ook voor kiezen (heb ik hierboven ook al aangehaald) om de adresgegevens los te koppelen van de tabellen waarin ze voorkomen. Dan maak je dus een aparte tabel voor adressen, en bij entiteiten waar dat nodig is (klanten, bedrijven) vul je de adreskaart in. Op die manier hou je de tabellen klein en overzichtelijk.

Voor ZZP-ers heb je een iets andere constructie nodig, want dat zijn eigenlijk ook bedrijven, maar dan éénmansbedrijven. Met dus dan 2 adressen, één als persoon en één als bedrijf. Ook hier geldt het voordeel van een aparte adrestabel; je kunt in beide tabellen (persoon en bedrijf) verwijzen naar hetzelfde adresID en bij adresmutaties hoef je dan maar één adres te muteren.

Om op je laatste vraag terug te komen: aparte tabellen voor klanten en leveranciers is dus niet altijd aan te raden. Zijn het absoluut (altijd één van de twee en ook toekomstig nooit overlappend) verschillende entiteiten, dan kan het handig zijn om de 2 te scheiden. In jouw geval dus niet :).
 
Super bedankt voor het uitgebreide en verhelderende antwoord, was wel een flinke boterham die even moest herkauwd worden eer het verhelderend werd, de eerste hitte doet het brein waarschijnlijk geen deugd.

Meteen werden ook de grove lijnen van de aan te maken tabellen meegegeven, en heb mijn reeds gemaakt brouwsel dan ook in die zin aangepast. Hiervan een print in bijlage, denk dat uw antwoord zo moest vertaald worden, en ik hiermee voldoende mogelijkheden te hebben voor het eerste opzet, een contactenbestand.

Uiteindelijk moet het opzet leiden tot een database die een volledige administratieve bedrijfsvoering beheert, en denk dan nu al wel vooruit, maar wil het modulair bouwen, en zorgen dat het eerste pakket doet wat het moet doen vooraleer met een volgende module te beginnen.

Ook bedankt om de koppeltabel onder mijn aandacht te brengen. Hiermee is meteen ook het voor in een volgend stadium overdacht probleem van “1 leverancier levert verschillende artikelen, en 1 artikel wordt door verschillende leveranciers geleverd “ opgelost.

Mijn tabellen: Bekijk bijlage Tabellen contacten.pdf
 
Je opzet ziet er niet verkeerd uit, je kunt daar zeker mee beginnen. Ik snap de code in de naamgeving voor de sleutelvelden nog wel, dus dat je een veld BD_ID noemt en niet ID, wat Access standaard gebruikt, is prima. Al gebruik ik liever de veldnaam Bedrijf_ID. En Contact_ID i.p.v. Ct_ID. Verder zou ik de veldnamen gewoon de veldnamen laten zijn; Firmanaam lijkt mij net zo duidelijk, zo niet duidelijker, dan bd_Firmanaam. Maar dat doet niets af aan de functionaliteit van de opzet.

Ook bedankt om de koppeltabel onder mijn aandacht te brengen. Hiermee is meteen ook het voor in een volgend stadium overdacht probleem van “1 leverancier levert verschillende artikelen, en 1 artikel wordt door verschillende leveranciers geleverd “ opgelost.
Dat is inderdaad standaard in een database. Een leverancier levert Artikelen, en een artikel kan doorgaans door meerdere leveranciers geleverd worden. In dat geval heb je een tabel tblLev_Levert nodig waarin je vastlegt welke leverancier welk artikel levert en tegen welke prijs. En wat je nog meer aan variabelen hebt. Een Ja/Nee veld [Leverbaar] lijkt mij ook wel handig; als een leverancier een artikel niet meer levert moet dat natuurlijk geregistreerd worden. En zo zijn er nog wel meer variabelen.
Wat je in ieder geval niet moet doen: keuzelijsten maken in je tabellen. Keuzelijsten (met invoervakken) gebruik je op formulieren maar niet in tabellen. Enige uitzondering: keuzelijsten op basis van waarden, zoals een keuzelijst voor [Geslacht]. Hier heb je een schamele 2 opties, dus een beetje onzinnig om daar een aparte tabel voor te maken.
Succes met bouwen :).
 
Weeral bedankt.

Ben wat aan het spelen geweest, en al een nieuw probleem tegen gekomen. Na het nodige zoekwerk zal ik maar een nieuwe vraag aanmaken.
Deze zet ik op opgelost.
 
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan