Van Google Sheet naar relationeel schema: een stapsgewijs modelleringsplan
Google Sheet naar relationeel schema, helder uitgelegd in praktische stappen: herken herhalende groepen, kies sleutels, breng relaties in kaart en voorkom later rommelige data.

Waarom spreadsheets rommelig worden als ze een database worden
Een spreadsheet is geweldig voor een kleine lijst. Je kunt kolommen ter plekke veranderen, overal notities toevoegen en problemen met het oog oplossen. Die vrijheid begint af te brokkelen zodra het bestand een gedeelde bron van waarheid wordt.
Naarmate data groeit, verschijnen steeds dezelfde problemen. Je ziet duplicaten omdat er geen enkele plek is om een klant of product op te slaan. Je krijgt tegenstrijdige waarden omdat twee rijen het over hetzelfde niet eens zijn, bijvoorbeeld een telefoonnummer. Filteren en rapporteren worden frustrerend omdat sommige kolommen lijsten verbergen ("Tags", "Products", "Attendees") of formaten mixen ("$1,200", "1200", "1.2k").
Overstappen van een Google Sheet naar een relationeel schema draait om veiligheid. Een database dwingt een duidelijkere structuur af zodat je kunt query'en, valideren en bijwerken zonder nieuwe tegenstrijdigheden te creëren.
Een nuttig mentaal model: één rij zou één echt ding moeten representeren. Als een rij een deal, een klant en een lijst met producten tegelijk voorstelt, wordt het later bijwerken van één daarvan pijnlijk.
Een snelle test: heeft een enkele rij ooit twee waarden nodig voor hetzelfde veld?
- Eén order heeft meerdere producten
- Eén project heeft meerdere teamleden
- Eén klant heeft meerdere adressen
Als het antwoord ja is, is het geen “brede rij”-probleem. Het is een “aparte tabel”-probleem. Zodra je het netjes modelleert, kun je formulieren en validatie bovenop bouwen in plaats van te vertrouwen op kwetsbare handmatige bewerkingen.
Begin met definiëren wat het sheet eigenlijk betekent
Een spreadsheet kan er georganiseerd uitzien en toch iets anders betekenen voor verschillende mensen. Voordat je een Google Sheet naar een relationeel schema converteert, stem af op wat het sheet bijhoudt.
Begin met uitkomsten, niet met kolommen. Welke beslissingen moet de data ondersteunen: een wekelijkse omzetrapportage, een lijst met achterstallige tickets, een workflow die opvolgingen toewijst, of snel opzoeken tijdens een klantgesprek? Als je geen beslissing kunt noemen, hoort dat veld vaak niet in de database.
Trek daarna de zelfstandige naamwoorden uit de headers en notities. Die worden meestal je toekomstige tabellen: customers, orders, products, invoices, tickets, agents, locations. Als een kolom twee zelfstandige naamwoorden mengt (zoals “Customer + Company”), sla je meerdere dingen op op één plek.
Kom vroeg overeen over definities
Kleine betekenissverschillen worden later grote opruimklusjes. Wees duidelijk over de basis:
- Wat telt als een “order” (een offerte, een betaalde aankoop of allebei)?
- Wat is een “customer” (persoon, bedrijf of beide)?
- Kan één order meerdere producten bevatten?
- Kan één e‑mail bij meerdere klanten horen?
- Wat moet “status” tonen (huidige staat of geschiedenis)?
Voorbeeld: als je sheet één rij per “Order” heeft maar de “Products”-cel een komma-gescheiden lijst bevat, bepaal dan of die rij een checkout, een verzending of een factuur vertegenwoordigt. Elke keuze leidt tot een ander schema.
Maak een bevroren kopie van het originele sheet als alleen-lezen. Die gebruik je om te controleren of de nieuwe tabellen nog steeds dezelfde vragen beantwoorden.
Maak het sheet schoon zodat de structuur zichtbaar wordt
Voordat je een Google Sheet naar een relationeel schema converteert, laat het sheet eruitzien als data, niet als een rapport. Databases hebben consistente rijen en kolommen nodig. Decoratieve layouts verbergen patronen die je moet modelleren.
Verwijder layouttrucs zoals samengevoegde cellen, meerdere header-rijen en subtotalen binnen het gegevensbereik. Hou één header-rij en daarna alleen rijen met records. Als je totalen nodig hebt, zet die op een aparte samenvattabblad zodat ze niet door elkaar gaan lopen met de echte records.
Maak daarna de formats consistent per kolom. Een database kan niet raden dat “1/2/24”, “2024-02-01” en “Feb 1” dezelfde datum zijn. Hetzelfde geldt voor telefoonnummers, valuta en namen. Kies één formaat en gebruik het overal, ook al voelt het strikt.
Een korte opschoningsronde die meestal loont:
- Zorg dat elke rij één ding vertegenwoordigt (één order, één klant, één ticket).
- Verwijder lege spacer-rijen en kolommen.
- Vervang “N/A”, “-” en lege strings door één regel die je aanhoudt.
- Markeer welke kolommen berekend zijn versus getypt door een persoon.
Markeer tenslotte elke cel die meerdere waarden bevat, zoals “red, blue, green” in één kolom. Los het schema nog niet op. Markeer die kolommen alleen zodat je onthoudt dat ze later aparte rijen worden.
Identificeer herhalende groepen en velden die lijsten verbergen
Het grootste waarschuwingssignaal in datamodellering met spreadsheets is herhaling. Sheets proppen vaak “meer dan één ding” in een enkele rij door kolommen te herhalen of meerdere waarden in één cel te stoppen. Dat werkt voor snel bijhouden en breekt zodra je wilt filteren, rapporteren of consistent updaten.
Patronen die meestal betekenen “dit hoort een andere tabel te zijn”
Scan op deze vormen:
- Genummerde kolommen zoals
Item 1,Item 2,Item 3ofPhone 1,Phone 2. - Herhaalde blokken zoals adresvelden gedupliceerd voor “Home” en “Work”.
- Cellen met komma's, regeleinden of “en” die waarden combineren (bijvoorbeeld “Mouse, Keyboard, Monitor”).
- Eén kolom die twee concepten mengt, zoals “Approved 2025-01-10” of “Alex (Manager)”.
- Een rij die twee niveaus tegelijk representeert, zoals een Order-rij die ook alle Order Items probeert op te slaan.
Voorbeeld: als je sales-tracker Order ID, Customer, Product 1, Qty 1, Product 2, Qty 2 gebruikt, loop je vast. Sommige orders hebben 1 item, andere 8. Het sheet groeit dan zijdelings voor altijd of begint data te verliezen. In een relationeel model wordt “Orders” één tabel en “Order Items” een andere tabel met één rij per product op de order.
Voor “lijsten in een cel” behandel elke waarde als een eigen record. Een cel met “Email, SMS” betekent meestal dat je een aparte tabel (of join-tabel) nodig hebt om kanalen netjes bij te houden.
Gemixte kolommen zijn stiller maar net zo risicovol. Splits ze vroeg zodat elk veld één duidelijke feit opslaat.
Maak tabellen van de gevonden entiteiten
Zodra je de echte dingen in het sheet kunt benoemen, zet je elk daarvan om in een eigen tabel. Je spreadsheet stopt met één groot raster en wordt een set kleinere, doelgerichte lijsten.
Als een rij details over twee verschillende dingen mengt, heeft het waarschijnlijk twee tabellen nodig. Een sales-tracker-rij kan klantinfo (naam, telefoon), orderinfo (datum, status) en productinfo (SKU, prijs) bevatten. Klanten veranderen niet elke keer dat een order verandert, en producten hangen niet van één order af. Splitsen voorkomt dubbele bewerkingen en mismatchende waarden.
Schrijf voordat je iets finaliseert een één-woordige zin die het doel van elke tabel beschrijft. Als je niet kunt beschrijven wat een tabel voorstelt zonder “en ook” te zeggen, is hij meestal te breed.
Een paar praktische regels:
- Houd attributen samen die hetzelfde ding beschrijven en dezelfde levenscyclus delen (customer name en customer email).
- Verplaats alles wat meerdere keren kan voorkomen naar een eigen tabel (meerdere order items, meerdere adressen).
- Als een cel een lijst bevat (komma-gescheiden waarden, herhaalde kolommen), is dat een aparte tabel.
- Als twee sets velden om verschillende redenen veranderen, scheid ze (order status versus klantcontactinfo).
Geef kolommen daarna duidelijke, consistente namen. Geef voorkeur aan simpele zelfstandige naamwoorden en vermijd vage labels als “Info” of “Details”.
Kies sleutels die stabiel blijven in de tijd
Kies vroeg een primaire sleutel voor elke tabel. Een goede sleutel is saai: hij verandert nooit, is altijd aanwezig en identificeert precies één rij.
Natuurlijke sleutels (echte wereldwaarden) kunnen werken, maar alleen als ze echt stabiel zijn. Een SKU is vaak een goede natuurlijke sleutel omdat die bedoeld is permanent te zijn. E‑mailadressen klinken stabiel, maar mensen veranderen e‑mails, delen inboxen en creëren duplicaten zoals “john@” en “john.work@”. Namen, telefoonnummers en adressen veranderen en zijn niet gegarandeerd uniek.
Een veilige standaard is een automatisch gegenereerde ID (zoals customer_id, order_id). Houd de natuurlijke identifier als normaal veld en voeg een uniciteitsregel toe wanneer dat past bij je bedrijfsregels. Als een e‑mail verandert, blijft customer_id gelijk en verwijzen gerelateerde orders nog steeds naar de juiste klant.
Eenvoudige sleutelregels:
- Gebruik een auto-ID wanneer de echte wereld-identifier kan veranderen, ontbreekt of hergebruikt kan worden.
- Gebruik een natuurlijke sleutel alleen wanneer je deze controleert en hij permanent is ontworpen (bijv. SKU).
- Markeer velden als uniek alleen wanneer duplicaten fout zouden zijn.
- Sta NULL toe alleen wanneer “onbekend” een geldige staat is; anders vereis een waarde.
- Schrijf op wat “uniek” betekent (uniek per tabel, per bedrijf of per tijdsperiode).
Voorbeeld: in een Contacts-tabel gebruik je contact_id als primaire sleutel. Houd email alleen uniek als je regel is dat één contact gelijk is aan één e‑mail. Sta phone leeg toe omdat niet iedereen er een heeft.
Breng relaties in kaart zonder te gokken
De meeste fouten komen door gokken hoe dingen zich verhouden. Gebruik een eenvoudige regel: als één rij veel van iets “bezit”, is dat één-op-veel. Zet de foreign key aan de “veel”-kant.
Voorbeeld: één Customer kan veel Orders hebben. De Orders-tabel moet customer_id opslaan. Als je een komma-gescheiden lijst met ordernummers in Customers bewaart, ontstaan snel duplicaten en ontbrekende data.
Veel-op-veel is de veelvoorkomende spreadsheet-val. Als één Order veel Products kan bevatten en één Product in veel Orders kan voorkomen, heb je een join-tabel nodig (meestal line items). Die bevat typisch order_id, product_id, plus velden zoals quantity en de prijs op het moment van aankoop.
One-to-one-relaties zijn zeldzaam. Ze maken zin wanneer extra data optioneel is of voor privacy/performance apart gehouden wordt (bijv. User en UserProfile). Ze zijn een waarschuwing wanneer je een tabel alleen splitst omdat het sheet twee tabs had.
Geschiedenis heeft zijn eigen structuur nodig. Als waarden in de loop van de tijd kunnen veranderen (status, prijs, adres), vermijd het overschrijven van één kolom. Sla wijzigingen op als rijen in een history-tabel zodat je kunt antwoorden op “wat was waar op die datum?”
Normaliseer genoeg om tegenstrijdigheden te voorkomen
Een simpele regel: sla één feit op één plek op. Als een klanttelefoon in vijf rijen staat, zal iemand er vier bijwerken en de vijfde missen.
Normalisatie in gewone taal:
1NF, 2NF, 3NF in praktische termen
First normal form (1NF) betekent dat elke cel één waarde bevat. Als een kolom “red, blue, green” of “SKU1|SKU2|SKU3” bevat, is dat een verborgen lijst. Breek het in rijen in een gerelateerde tabel.
Second normal form (2NF) verschijnt het meest bij line items. Als je OrderItems hebt en de sleutel is (OrderID, ProductID), dan horen velden als CustomerName daar niet thuis. Die hangen af van de order, niet van het product.
Third normal form (3NF) betekent dat niet-sleutelvelden niet mogen afhangen van andere niet-sleutelvelden. Voorbeeld: als je ZipCode en City opslaat en City door ZipCode wordt bepaald, loop je het risico op inconsistenties.
Een korte zelfcheck:
- Kan dezelfde waarde op meer dan één plek worden bewerkt?
- Zou één wijziging je dwingen veel andere rijen te updaten?
- Sla je labels op die afgeleid kunnen worden van een ID?
- Worden totalen opgeslagen naast de ruwe rijen die ze produceren?
Wanneer denormaliseren oké is
Denormaliseer hoofdzakelijk voor read-heavy rapportage, en doe het veilig: behandel de rapportagetabel als een kopie die je kunt herbouwen. Houd genormaliseerde tabellen als de bron van waarheid.
Voor afgeleide waarden zoals totalen, saldi en status, dupliceer ze niet tenzij je een duidelijke regel hebt om ze opnieuw te berekenen. Een praktische aanpak: sla ruwe transacties op, bereken totalen in queries en cache totalen alleen wanneer performance het echt vereist.
Veelvoorkomende modelleringsvallen die later opruimen veroorzaken
De meeste “het werkte in het sheet”-problemen komen door betekenis, niet door tools. Het doel is dat elke rij één duidelijk ding zegt, op precies dezelfde manier, elke keer weer.
Veelvoorkomende valkuilen:
- Namen als ID's gebruiken. “John Smith” is geen unieke identifier en namen veranderen. Gebruik een gegenereerde ID (of een geverifieerde e‑mail of telefoon) en behandel weergavenaam als label.
- Lijsten in één cel proppen. Het lijkt eenvoudig, maar het breekt zoeken, validatie en rapportage. Lijsten horen in een gerelateerde tabel.
- Huidige staat mengen met geschiedenis. Eén Status-kolom kan je niet zowel de laatste status als hoe die veranderde vertellen. Als timing belangrijk is, sla statuswijzigingen op als events met timestamps.
- Één tabel overladen met meerdere betekenissen. Een Contacts-sheet dat klanten, leveranciers en medewerkers bevat, eindigt meestal met velden die alleen op sommige rijen van toepassing zijn. Split door rol, of houd een gedeelde Person-tabel en voeg rol-specifieke tabellen toe.
- Vereiste versus optionele velden negeren. Als cruciale velden leeg kunnen zijn, krijg je rijen die niet netjes joinen. Bepaal wat vereist is en handhaaf het vroeg.
Als je Orders-tabel kolommen heeft als Item 1, Item 2, Item 3, kijk je naar een herhalende groep. Plan dan voor een Orders-tabel plus een OrderItems-tabel.
Snelle checklist voordat je het schema vastlegt
Voordat je het schema vergrendelt, doe een laatste controle op duidelijkheid. De meeste databasepijn later komt van kleine shortcuts die in het begin onschuldig leken.
Vraag jezelf of elke tabel één simpele vraag beantwoordt. “Customers” moet klanten betekenen, niet klanten plus hun laatste order plus gespreksnotities. Als je een tabel niet in één korte zin kunt beschrijven, mixt hij meestal dingen.
Laatste controles:
- Kun je aanwijzen welke kolom (of set kolommen) elke rij uniek identificeert, zelfs als namen veranderen?
- Bevaten enige cellen meer dan één waarde (komma-gescheiden tags, meerdere e‑mails, Item1/Item2-kolommen)? Zo ja, split naar een child-table.
- Is voor elke relatie een bewuste foreign key opgeslagen? Heb je voor many-to-many een join-tabel?
- Hebben belangrijke velden regels (verplicht waar ontbrekende data het proces breekt, uniek waar duplicaten schadelijk zijn)?
- Kun je een feit (klantadres, productprijs, medewerkerrol) op precies één plek bijwerken?
Reality-check: stel je voor dat iemand dezelfde klant twee keer intypt met een licht andere spelling. Als je schema dat makkelijk maakt, voeg dan een betere sleutel of een uniciteitsregel toe.
Voorbeeld: een sales-tracker-sheet omzetten naar schone tabellen
Stel je een sales-tracker voor waar elke rij een deal is. Kolommen zoals Customer Name, Customer Email, Deal Amount, Stage, Close Date, Products (een komma-gescheiden lijst) en Notes (soms meerdere notities in één cel).
Die ene rij verbergt twee herhalende groepen: products (één deal kan veel producten bevatten) en notes (één deal kan veel notities hebben). Hier gaan conversies vaak mis, omdat lijsten in cellen moeilijk te query'en en makkelijk tegenstrijdig zijn.
Een schoon “na”-model dat overeenkomt met hoe het werk zich daadwerkelijk gedraagt:
- Customers (CustomerId, Name, Email)
- Deals (DealId, CustomerId, Amount, Stage, CloseDate)
- Products (ProductId, Name, SKU)
- DealProducts (DealId, ProductId, Quantity, UnitPrice)
- DealNotes (NoteId, DealId, NoteText, CreatedAt)
CustomerId, DealId en ProductId zijn stabiele identifiers. DealProducts lost de veel-op-veel-relatie op: één deal kan veel producten bevatten en één product kan in veel deals voorkomen. DealNotes houdt notities apart, zodat je niet eindigt met “Note 1, Note 2, Note 3” kolommen.
Voor de conversie betekent een rapport als “omzet per product” eerst strings splijten en hopen dat mensen consequent namen hebben getypt. Na modellering is het een eenvoudige query over DealProducts joined met Deals en Products.
Volgende stappen: ga van schema naar een werkende app
Zodra je schema op papier goed voelt, zet je het in een echte database en test je met echte data. Importeer niet meteen alles. Laad eerst een kleine batch, los op wat breekt en herhaal.
Een praktische volgorde die risico laag houdt:
- Maak de tabellen en relaties aan.
- Importeer 50 tot 200 rijen, verifieer totalen en check steekproefsgewijs records.
- Los mappingproblemen op (verkeerde kolommen, ontbrekende ID's, duplicaten) en importeer opnieuw.
- Wanneer het stabiel is, laad de rest.
Voeg vroeg valideringsregels toe zodat slechte spreadsheet-gewoonten niet terugkomen. Maak verplichte velden echt verplicht, beperk toegestane waarden (zoals status), valideer formaten (datums en e‑mails) en gebruik foreign keys zodat je geen order voor een niet-bestaande klant kunt maken.
Stop daarna met het gebruiken van de sheet voor updates. Je data beschermen wordt veel eenvoudiger wanneer mensen eenvoudige formulieren en duidelijke workflows gebruiken.
Als je het schema zonder te programmeren in een werkende interne tool wilt omzetten, kan AppMaster (appmaster.io) helpen: je modelleert tabellen en relaties visueel en genereert vanuit hetzelfde model een productieklare backend, webapp en native mobiele apps.
FAQ
Begin wanneer de sheet als gedeelde bron van waarheid fungeert en je duplicaten, tegenstrijdige waarden of frustrerende rapportages ziet. Als je vecht met komma-gescheiden lijsten, Item 1/Item 2-kolommen of constant kopiëren/plakken om fouten te herstellen, bespaart een relationeel schema snel veel tijd.
Als één rij meerdere waarden voor hetzelfde veld nodig heeft, heb je een herhalende groep. Voorbeelden: meerdere producten op één bestelling, meerdere adressen voor één klant, of meerdere deelnemers voor één evenement. Die horen thuis in child-tables (of join-tables), niet in extra kolommen of lijsten in één cel.
Maak een bevroren, alleen-lezen kopie van het originele sheet en verwijder samengevoegde cellen, meerdere header-rijen en subtotalen uit het gegevensbereik. Zorg dat elke kolom consistent is (één datumformaat, één valutaformaat, één manier om lege waarden te representeren) zodat je de echte structuur ziet voordat je gaat modelleren.
Gebruik standaard een automatisch gegenereerde ID voor elke tabel omdat die stabiel is en niet verandert als mensen e-mails, namen of telefoonnummers bijwerken. Bewaar echte wereld-identifiers (zoals e‑mail of SKU) als normale velden en voeg een uniciteitsregel toe alleen wanneer duplicaten echt onacceptabel zijn voor je bedrijfsregels.
Map het door eigenaarschap: als één klant veel bestellingen kan hebben, zet dan customer_id op de Orders-tabel. Als het veel-op-veel is (bestellingen en producten), voeg dan een join-tabel toe zoals OrderItems met order_id, product_id plus hoeveelheid en prijs op dat moment.
Omdat het tegenstrijdigheden voorkomt. Eén feit op één plek opslaan betekent dat je het één keer bijwerkt en alles consistent blijft. Je hoeft geen “perfecte” normalisatie te doen, maar vermijd duplicaten zoals hetzelfde klanttelefoonnummer verspreid over veel rijen.
Splits het in juiste rijen. Een cel als “Email, SMS” is moeilijk te filteren en valideren en breekt rapportages. Maak een gerelateerde tabel (of join-tabel) waarin elke geselecteerde waarde een eigen record wordt die terugkoppelt naar de parent-rij.
Scheid “huidige staat” van “geschiedenis”. Hou een huidig statusveld als je het direct nodig hebt, maar leg wijzigingen als rijen vast in een history/events-tabel met timestamps wanneer timing belangrijk is. Zo kun je vragen beantwoorden als “wat was de status vorige maand?” zonder te gissen.
Importeer eerst een kleine batch (ongeveer 50–200 rijen), controleer totalen en vergelijk steekproefsgewijs records met het bevroren sheet. Los mappingproblemen, ontbrekende ID's en duplicaten op en importeer opnieuw. Laad pas alles zodra het proces herhaalbaar en voorspelbaar is.
Een no-code tool kan helpen wanneer je het schema wilt omzetten in een werkende app met formulieren, validatie en workflows, niet alleen tabellen. AppMaster (appmaster.io) kan helpen: je modelleert tabellen en relaties visueel en genereert een productieklare backend, webapp en native mobiele apps vanuit hetzelfde model.


