Normaliseren van combinaties

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • Megamind
  • Registratie: Augustus 2002
  • Laatst online: 10-09 22:45
Ik zit hier al een tijdje over te denken en heb al wat gegoogled maar misschien gebruik ik de verkeerde termen.

Ik heb een database met een tabel producten:
code:
1
2
3
4
5
6
7
-----------
| Product |
| ------- |
| ProdID  |
| Naam    |
| Omschr. |
-----------

Product bevat dus niets anders dan de naam en het ID, geen prijzen en levertijden e.d.

Nu heb ik ProductTypes
code:
1
2
3
4
5
6
7
---------------
| ProductType |
| ----------- |
| ProductId   |
| Prijs       |
| Levertijd   |
---------------


Probleem is dat ik graag meerdere varianten van een product wil toevoegen die hangen aan het product zelf, bv de maat.

Het makkelijkst is om een kolom "maat" erbij te maken bij ProductTypes, maar dit schaalt horizontaal. Ik wil het graag verticaal kunnen schalen want er kunnen N aantal types bijkomen welke met elkaar correleren.

Bijvoorbeeld want ik nu kan hebben:
code:
1
2
3
4
5
6
7
8
9
10
11
12
--------------------------------------
| ProductId   | Maat | Kleur | Prijs |
| ----------- | -----|-------|--------
| 1           | S    | Geel  | €5,00 |
| 1           | L    | Geel  | €6,00 |
| 1           | S    | Paars | €7,00 |
| 1           | L    | Paars | €8,00 |
| 2           | XS   | Geel  | €5,00 |
| 2           | XL   | Geel  | €6,00 |
| 2           | XS   | Paars | €7,00 |
| 2           | XS   | Paars | €8,00 |
--------------------------------------


Nu snap ik best dat Maat en Kleur een aparte tabel worden zodat ze niet dubbel in de DB staan, maar het is een voorbeeld. Dit is in princiepe gewoon een 2 tabel.

Als ik nu een 3e type erbij wil hebben dan moet ik dus de tabel horizontaal uitbreiden met bv "opdruk" en erger wordt het nog als er andere soorten producten bijkomen, bv geheugenkaarten waarbij de prijs een correlatie is van de klasse en de opslagruimte.

Ik wil dit dus verticaal kunnen opslaan maar hoe kan ik dit nu netjes normaliseren?

Acties:
  • 0 Henk 'm!

  • upje
  • Registratie: April 2001
  • Laatst online: 06-10 18:39
Je hebt denk ik nog 2 tabellen nodig, ik noem ze even ProductEigenschapType en ProductEigenschapCombi

ProductEigenschapType:
TypeId Omschrijving
1 Maat
2 Kleur
3 Prijs

en dan ProductEigenschapCombi

CombiId ProductId TypeId Waarde
1 1 1 S
1 1 2 Geel
1 1 3 5
2 1 1 L
2 1 2 Geel
2 1 3 6

Je kan ook nog het waardebereik van de ProductEigenschapTypes (maat, kleur) in een tabel opslaan. En misschien dat je de kolom Waarde in de tabel hierboven nog moet opsplitsen naar WaardeString en WaardeNumeriek, zodat je beter met aantallen en prijzen kan werken.

Acties:
  • 0 Henk 'm!

Verwijderd

upje schreef op zondag 03 november 2013 @ 08:36:
Je hebt denk ik nog 2 tabellen nodig, ik noem ze even ProductEigenschapType en ProductEigenschapCombi
En stel ik wil nu een overzicht van alle producten die geel zijn, niet groter dan L en waarvan er minder dan 10 op voorraad zijn, en waarvan de prijs afwijkt van hetzelfde product in een andere kleur.

Acties:
  • 0 Henk 'm!

  • storeman
  • Registratie: April 2004
  • Laatst online: 06-10 23:22
Ten eerste vind ik de term "ProductType" niet zo handig gekozen. Product is van een bepaald type. Jij hebt het over de uitvoering.

Je kunt dit op meerdere manieren oplossen. Voor een soortgelijk probleem, heb ik de tabellen:

- ItemType
- Item
- ItemTypeProperties
- ItemPropertyValues

Hier binnen bestaan de volgende relaties:

code:
1
2
3
4
5
6
7
8
Item.id_item_type = ItemType.id

ItemTypeProperties.id_item_type = ItemType.id

ItemTypePropertyValues.id_item_type_property = ItemTypeProperties.id

ItemPropertyValues.id_property = ItemTypePropertyValues.id
ItemPropertyValues.id_item = Items.id


Je kunt bij je item nu gewoon de prijs opslaan, of je maakt hiervoor nog een losse tabel omdat je misschien straks een keer een prijsverhoging hebt per bepaalde datum? Zo kun je geldigheid van prijzen opslaan.


Een andere optie is om aan de slag te gaan met NoSQL databases. Deze gegevens kun je mooi opslaan in een document. Postgresql heeft hiervoor HStore, wellicht dat er een mysql variant is.
En stel ik wil nu een overzicht van alle producten die geel zijn, niet groter dan L en waarvan er minder dan 10 op voorraad zijn, en waarvan de prijs afwijkt van hetzelfde product in een andere kleur.
Dan moet je daar een query voor schrijven :P. Je kunt joinen of met "IN" voorwaarden werken.

"Chaos kan niet uit de hand lopen"


Acties:
  • 0 Henk 'm!

Verwijderd

storeman schreef op zondag 03 november 2013 @ 09:05:
Dan moet je daar een query voor schrijven :P. Je kunt joinen of met "IN" voorwaarden werken.
Er zitten wat kleine praktische problemen verborgen in mijn vraag. Problemen die bij grote databases groter worden. Je gaat bijvoorbeeld een probleem krijgen omdat er geen fatsoenlijke indexen kunnen worden bijgehouden. En omdat er geen volgorde duidelijk is tussen verschillende kledingmaten.

Ik kan in 3 minuten meer problemen voor je bedenken dan je met 3 weken ontwikkeltijd kunt oplossen als je de verkeerde keuzes hebt gemaakt.

Daarvoor schrijf je dan niet meer even een query. Daarvoor kun je dan je databasestructuur gaan omgooien.
Wees voorzichtig met het aanraden van een database in een database, of het gebruik maken van noSQL. Er zullen hier genoeg mensen rondlopen die nachtmerries hebben over hun databaseontwerpen in het verleden.

Acties:
  • 0 Henk 'm!

  • upje
  • Registratie: April 2001
  • Laatst online: 06-10 18:39
Verwijderd schreef op zondag 03 november 2013 @ 09:04:
[...]

En stel ik wil nu een overzicht van alle producten die geel zijn, niet groter dan L en waarvan er minder dan 10 op voorraad zijn, en waarvan de prijs afwijkt van hetzelfde product in een andere kleur.
Dat zal inderdaad een query worden die wat lastiger is dan gebruikelijk.

Als je dat allemaal niet wilt, dan zit je er aan vast dat elke eigenschap van een product een veld in de tabel product wordt. Heel overzichtelijk, maar als er een extra producteigenschap moet worden vastgelegd, dan moet het datamodel worden gewijzigd. Dit lijkt me alleen een optie als het aantal eigenschappen van een product maar zeer zelden veranderd.

Acties:
  • 0 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 27-09 13:03
Je lijkt een beetje allergisch voor het maken van kolommen in je tabel. Waarom is dat?

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Acties:
  • 0 Henk 'm!

  • Megamind
  • Registratie: Augustus 2002
  • Laatst online: 10-09 22:45
Omdat ik een product heb waar een paar 100 klanten hun ding op doen. Hoe ga ik dat beheren? Horizontaal schalen op een productieomgeving is gewoon not-done :P

Maar misschien is het makkelijk om 10 of 20 kolommen vast te zetten waarbij er dus maximaal 10-20 verschillende combinaties aangehangen kunnen worden.

[ Voor 32% gewijzigd door Megamind op 03-11-2013 16:40 ]


Acties:
  • 0 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 27-09 13:03
Denk het ook eigenlijk, het "database-in-database" verhaal gaat bij een dergelijke toepassing volgens mij helemaal niet werken.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Als je inderdaad een paar honderd klanten in die omgeving hebt werken die allemaal hun eigen producten erin kwijt willen, dan kun je zeer waarschijnlijk op sommige vlakken beter denormaliseren dan normaliseren. Ik heb een keer een vergelijkbare situatie gehad waarbij het eindresultaat in een genormaliseerde database was dat het systeem niet vooruit te branden was. Gelukkig kwam dat tijdens tests naar voren tijdens het maken van een POC, dus ik kon vrij snel schakelen naar een wat plattere database die weliswaar niet helemaal netjes is, maar wel performt. :)

Het probleem in dit geval is een beetje dat je voor een goed genormaliseerd systeem twee keuzes hebt: ofwel je gaat in abstracten werken (ProductProperty en ProductPropertyOption waar je respectievele "maat" en "L" in kwijt zou kunnen), ofwel je zit vast aan een tabel per type kenmerk (waarbij je je producttabel ook weer horizontaal moet uitbreiden). Het eerste heeft al gauw consequenties voor de performance, het tweede is een draak om te onderhouden wanneer er eens een klant een nieuw soort product wil gaan verkopen.

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • Hydra
  • Registratie: September 2000
  • Laatst online: 06-10 13:59
Megamind schreef op zondag 03 november 2013 @ 06:38:
Ik wil dit dus verticaal kunnen opslaan maar hoe kan ik dit nu netjes normaliseren?
M.i. ben je nogal doorgeslagen. Welk nut heeft het om voor al die producten verschillende structuren te maken? Uiteindelijk zijn geheugenkaarten ook gewoon aparte producten met elk aparte barcodes en prijzen e.d. Je maakt het gewoon onnodig complex.

https://niels.nu


Acties:
  • 0 Henk 'm!

  • Megamind
  • Registratie: Augustus 2002
  • Laatst online: 10-09 22:45
Hydra schreef op zondag 03 november 2013 @ 18:46:
[...]


M.i. ben je nogal doorgeslagen. Welk nut heeft het om voor al die producten verschillende structuren te maken? Uiteindelijk zijn geheugenkaarten ook gewoon aparte producten met elk aparte barcodes en prijzen e.d. Je maakt het gewoon onnodig complex.
Omdat het de specificatie is?
NMe schreef op zondag 03 november 2013 @ 18:46:
Als je inderdaad een paar honderd klanten in die omgeving hebt werken die allemaal hun eigen producten erin kwijt willen, dan kun je zeer waarschijnlijk op sommige vlakken beter denormaliseren dan normaliseren. Ik heb een keer een vergelijkbare situatie gehad waarbij het eindresultaat in een genormaliseerde database was dat het systeem niet vooruit te branden was. Gelukkig kwam dat tijdens tests naar voren tijdens het maken van een POC, dus ik kon vrij snel schakelen naar een wat plattere database die weliswaar niet helemaal netjes is, maar wel performt. :)

Het probleem in dit geval is een beetje dat je voor een goed genormaliseerd systeem twee keuzes hebt: ofwel je gaat in abstracten werken (ProductProperty en ProductPropertyOption waar je respectievele "maat" en "L" in kwijt zou kunnen), ofwel je zit vast aan een tabel per type kenmerk (waarbij je je producttabel ook weer horizontaal moet uitbreiden). Het eerste heeft al gauw consequenties voor de performance, het tweede is een draak om te onderhouden wanneer er eens een klant een nieuw soort product wil gaan verkopen.
Opzich kan ik het vrij eenvoudig onderhouden door een vast aantal kolommen te maken met genormaliseerde types/properties hoe je het wilt noemend. Dan heb je alleen een hardcoded limiet van X aantal kolommen per product, maar dat is te overzien.

[ Voor 64% gewijzigd door Megamind op 03-11-2013 20:47 ]


Acties:
  • 0 Henk 'm!

  • Hydra
  • Registratie: September 2000
  • Laatst online: 06-10 13:59
En daar heb jij geen invloed op?

https://niels.nu


Acties:
  • 0 Henk 'm!

  • Megamind
  • Registratie: Augustus 2002
  • Laatst online: 10-09 22:45
Jawel, daarom zeg ik ook wat ik hierboven opper :P

En daarom onderzoek ik nu eerst óf het mogelijk is. Dus ja het is mogelijk maar omslachtig en teveel haken en ogen :)

Acties:
  • 0 Henk 'm!

  • jbdeiman
  • Registratie: September 2008
  • Laatst online: 07:12
Megamind schreef op zondag 03 november 2013 @ 16:39:
Omdat ik een product heb waar een paar 100 klanten hun ding op doen. Hoe ga ik dat beheren? Horizontaal schalen op een productieomgeving is gewoon not-done :P

Maar misschien is het makkelijk om 10 of 20 kolommen vast te zetten waarbij er dus maximaal 10-20 verschillende combinaties aangehangen kunnen worden.
Dit behoeft mogelijk nog meer uitleg:

Is het 1 product, waarbij alle klanten in een eigen losstaande installatie van dat product werken, of is het 1 omgeving waar alle klanten op werken?

Over het algemeen is normaliseren zeker wel handig, ook in een omgeving waar verschillende klanten gelijktijdig in aan het werk zijn, mogelijk met nog andere eigenschappen van producten tot gevolg.

Als ik jou vraag zo lees gaat het momenteel alleen om kleding, maar wat als klanten straks meer eigenschappen willen gaan bijhouden, of zelfs andere producten willen gaan verkopen? Dan is het wel goed om nu (gezien je vraag is de huidige structuur redelijk eenvoudig) goed uit te denken en uit te werken.

De opmerkingen die al gemaakt zijn wil ik eigenlijk niet herhalen, maar:
  • Normaliseren is een manier om een database zo op te bouwen dat je gegevens er zonder (te veel!) redundantie in opgeslagen kunnen worden. Ik noem expres "te veel" omdat het soms te ver doorgevoerd wordt.
  • Normaliseren is geen doel op zich, als je met een ongenormaliseerde structuur betere prestaties hebt en je benodigde flexibiliteit, ga dan niet verder normaliseren.
Overigens:
Een paar 100 klanten, maar hoeveel producten en dergelijke zitten in jou database? (wat is de totale omvang (ongeveer) van je database? Mocht dit redelijk binnen de perken blijven, dan kan je prima door normaliseren. De juiste relaties tussen tabellen leggen en de juiste indexes toepassen om snel te kunnen zoeken is bij een (relatief) kleine database prima te doen.

Acties:
  • 0 Henk 'm!

  • Megamind
  • Registratie: Augustus 2002
  • Laatst online: 10-09 22:45
Ik heb het voor nu zo opgelost:

De productentabel heb ik nu zo gemaakt:
code:
1
2
3
4
5
6
7
8
9
10
11
12
--------------------------------------
| ProductId   | Type1 | Type2 | Prijs |
| ----------- | -----|-------|--------
| 1           | 1    | 5     | €5,00 |
| 1           | 2    | 5     | €6,00 |
| 1           | 3    | 5     | €7,00 |
| 1           | 4    | 5     | €8,00 |
| 2           | 1    | 6     | €5,00 |
| 2           | 2    | 6     | €6,00 |
| 2           | 3    | 6     | €7,00 |
| 2           | 4    | 6     | €8,00 |
--------------------------------------


Waarbij Type1 en Type2 nu dus hardcoded zijn. Een klant kan dan zelf een Type aanmaken:
code:
1
2
3
4
5
6
7
8
9
10
-----------------------------
| TypeId | Name | TypeGroup |
| ------ | -----|-----------|
| 1      | S    | Maat      |
| 2      | M    | Maat      |
| 3      | L    | Maat      |
| 4      | XL   | Maat      |
| 5      | Geel | Kleur     |
| 5      | Groen| Kleur     |
-----------------------------

Waarbij TypeGroup uiteraard weer genormaliseerd is, maar voor dit voorbeeld ga ik dat niet uittekenen.

Nu heb ik een limiet van 2 combinaties per product (Type1 en Type2) omdat deze horizontaal in de tabel staan, in het echie zal ik er hier 3 van maken, ik verwacht namelijk niet dat er producten zijn waarbij meer dan 3 types kan speciferen.

De kleding is maar een voorbeeld het gaat hier nog om een concept wat uitgewerkt wordt, nog niets staat dus zwart op wit.

[ Voor 4% gewijzigd door Megamind op 03-11-2013 22:16 ]


Acties:
  • 0 Henk 'm!

  • Hydra
  • Registratie: September 2000
  • Laatst online: 06-10 13:59
Aangezien je dus kennelijk een 1:N relatie hebt, is een koppeltabel tussen product en type voor de hand liggend. Dan kunnen klanten zoveel types als ze willen aan een product hangen.

https://niels.nu


Acties:
  • 0 Henk 'm!

  • Megamind
  • Registratie: Augustus 2002
  • Laatst online: 10-09 22:45
Ik heb nu een 1:N tabel inderdaad, maar de originele vraag was om die Type1 en Type2 te normaliseren.

Acties:
  • 0 Henk 'm!

  • Hydra
  • Registratie: September 2000
  • Laatst online: 06-10 13:59
Megamind schreef op zondag 03 november 2013 @ 23:45:
Ik heb nu een 1:N tabel inderdaad, maar de originele vraag was om die Type1 en Type2 te normaliseren.
Te denormaliseren bedoel je?

Je gebruikt termen nogal doormekaar. Zoals je het hebt over horizontaal / verticaal schalen, dat heeft bijzonder weinig met databases te maken.

Ik begrijp niet wat nu precies het issue is. Een product kan X 'types' hebben. Dus koppeltabel. Klaar.

[ Voor 33% gewijzigd door Hydra op 03-11-2013 23:49 ]

https://niels.nu


Acties:
  • 0 Henk 'm!

  • Megamind
  • Registratie: Augustus 2002
  • Laatst online: 10-09 22:45
Dan begrijp je het probleem niet.

Een Product X kan een kleur hebben en een maat, de prijs is afhankelijk van beide. Dit kan je prima opslaan in een koppeltabel. En wat als er nu nog iets bijkomt, lengte bv. Dan heb je een prijs die afhankelijk is van prijs, kleur en lengte.

Acties:
  • 0 Henk 'm!

  • TheNephilim
  • Registratie: September 2005
  • Laatst online: 06-10 11:28

TheNephilim

Wtfuzzle

Wat de structuur betreft, ik gebruik meestal:

Product + Product_Attributes = Product_Variation

De eerste is het algemene product, wat je dus ziet in het producten overzicht. De product attributen zijn eigenschappen die een product kan kan hebben. Bijvoorbeeld maat, kleur of iets dergelijks. Een product variatie is een combinatie van die twee en bevat een prijs en levertijd/voorraad informatie.

Kortom; zou je het netjes in elkaar willen zetten, dan kun je gebruik maken van drie tabellen. Maar... zoals hierboven ook genoemd, bekijk wel even of je echt product variaties nodig hebt.
NMe schreef op zondag 03 november 2013 @ 18:46:
Als je inderdaad een paar honderd klanten in die omgeving hebt werken die allemaal hun eigen producten erin kwijt willen, dan kun je zeer waarschijnlijk op sommige vlakken beter denormaliseren dan normaliseren. Ik heb een keer een vergelijkbare situatie gehad waarbij het eindresultaat in een genormaliseerde database was dat het systeem niet vooruit te branden was. Gelukkig kwam dat tijdens tests naar voren tijdens het maken van een POC, dus ik kon vrij snel schakelen naar een wat plattere database die weliswaar niet helemaal netjes is, maar wel performt. :)

Het probleem in dit geval is een beetje dat je voor een goed genormaliseerd systeem twee keuzes hebt: ofwel je gaat in abstracten werken (ProductProperty en ProductPropertyOption waar je respectievele "maat" en "L" in kwijt zou kunnen), ofwel je zit vast aan een tabel per type kenmerk (waarbij je je producttabel ook weer horizontaal moet uitbreiden). Het eerste heeft al gauw consequenties voor de performance, het tweede is een draak om te onderhouden wanneer er eens een klant een nieuw soort product wil gaan verkopen.
In het plattere geval, zou je dan gewoon meerdere platte producten aanmaken en hoe combineer je dat weer netjes aan de buitenkant? Een product met meerdere kleuren/maten/etc. wil je immers maar één keer weergeven om daarna de klant de kleur/maat/etc. te laten kiezen.

Altijd lastig, de balans vinden tussen onderhoudbaarheid, performance en soms de usability.

Acties:
  • 0 Henk 'm!

Verwijderd

Ook al is dit topic al 5 jaar oud, ik ga er toch een reply op geven.

Ik had zelf voorheen dingen zoals maten en kleuren in aparte tabellen zitten. Dat was bij zelfbouw. Bij bijvoorbeeld OpenCart kan je wel opties aanmaken zoals maat en kleur, maar als je daar een voorraad aan wilt hangen, dan klopt het niet, want maat/kleur is al een combi op zich. Dan zou je opties Zwart M, Zwart L en Zwart XL moeten aanmaken, en dat voor elke kleur, pas dan zal het werken. Dat is ook veel dubbel, niet echt ideaal. Dus vandaar dat ik zelf maar een aantal keer het wiel heb proberen uit te vinden. Maar goed, ik heb in de loop der tijd en ook dit jaar weer te maken gehad met het importeren van producten. En toen kwamen ze in alle gevallen met compleet platte lijsten. Zoiets als dit:

SKU100, EAN2002123, Broek Crazy, Blauw, M, € 30,-
SKU106, EAN2002124, Broek Crazy, Blauw, L, € 32,-
SKU111, EAN2002125, Broek Crazy, Blauw, XL, € 35,-
SKU120, EAN2002127, Broek Crazy, Rood, S, € 30,-
SKU130, EAN2002128, Broek Crazy, Rood, M, € 31,-
SKU140, EAN2002129, Broek Crazy, Rood, L, € 32,-
SKU150, EAN2002133, Broek Crazy, Groen, XXL, € 37,-

M.a.w. alles was compleet plat. Op zich ook niet zo gek, want elke productvariatie is gewoon een los product en heeft een unieke EAN, ook al is het alleen een andere maat of kleur oftewel een variantie van een ander product. Als je dit soort platte lijsten wilt importeren, dan kan je beter ook niet teveel tabellen hebben.

Ik ga nu eens een keer gewoon 1 platte producten-tabel maken. Daar komt dus o.a. het SKU en EAN in, de artikelnaam, omschrijving, prijs, de kleur en ook een maatveldje. Verder een hoofdafbeelding veldje en een tussentabel voor eventuele meerdere afbeeldingen die je pas op de productdetailpagina ziet. En ook een veldje 'parent' wat naar de id van zo'n zelfde product kan verwijzen (met de hoofd-maat), die kan je dan voor de soortgelijke producten met verschillende maten gebruiken. En dan denk ik ook nog een groepeer veldje of tabel, om de dezelfde producten met verschillende kleuren te groeperen, net zoals bij de Decathlon en Zalando. In het overzicht laat Zalando overigens alle kleurvariaties als losse producten voorbij komen, Decathlon niet (altijd), dan zie je er veel minder in het overzicht. Maar dat is een keuze.

Ik ben benieuwd wat voor een rare dingen ik onderweg ga tegenkomen. :) Je kan zeggen dat elk product er dan 10x dubbel in komt te staan, maar ja, ik hoef niet elke keer de titel in te vullen en de omschrijving enzo, dat doe ik alleen bij het 'hoofdartikel', en de maat, kleur, prijs en ean en voorraad moet je toch sowieso al los invoeren. Dus zo heel gek veel scheelt het ook niet, en het is wel lekker snel en makkelijk met importeren.
Pagina: 1