Black Friday = Pricewatch Bekijk onze selectie van de beste Black Friday-deals en voorkom een miskoop.

[Database / SQL] Database ontwerp voor onderdelen

Pagina: 1
Acties:

  • mrfatmen
  • Registratie: Februari 2001
  • Laatst online: 13:03
Ik ben momenteel bezig met het overzetten van een database met (auto) onderdelen van een Multivalue database (Pick / D3nt) naar een relationele database (msSQL 2005).
Voor het grootste gedeelt van de database is dit geen probleem, echter over 1 stuk heb ik zo mijn twijfels.

Namelijk de onderdelen zelf, we hebben ongeveer 1100 verschillende onderdelen in de database welke allemaal verschillende velden (specificaties) bevatten. Totaal hebben we z'n 150 verschillende velden voor deze onderdelen. In Pick maakt het niet uit dat een record uit ruim 150 velden bestaat waarvan telkens maar een klein aantal gevuld is. In msSQL is dit uiteraard een ander verhaal om het aantal velden in te perken kwam ik op het volgende ontwerp:
Afbeeldingslocatie: http://www.mrfatmen.nl/images/db.PNG
Tussen Delen.KopId en Koppen.KopId loopt uiteraard ook een relatie. Deze is helaas niet op het plaatje gekomen.


Het plaatje zegt waarschijnlijk meer dan woorden maar toch even kort.
In de delen tabel zit een KopId waar mee in een koppeltabel (Koppen) de bijbehorende velden opgezocht kunnen worden. De voorraad tabel bevat de unieke voorraad regels welke linken naar de Koppeltabel (voorraadvelden) welke de waarde van de velden bevat.

Dit ziet er naar mijn idee redelijk uit, echter heb ik het probleem dat ik de voorraad niet kan selecteren doormiddel van een sql-regel.
De bedoeling is dat ik een select van voorraad opvraag en netjes alle velden terugkrijg.
Welke ik dan naast elkaar in een gridview kan display'en om de gebruiker een overzicht te geven.
De enige 2 methoden die lijken te werken zijn de volgende.

1. Aparte selects
SQL:
1
2
3
4
5
6
7
8
9
10
11
12
 -- Als eerste deze query
SELECT     Debiteuren.Rode_Naam, Voorraad.BijzonderheidInet
FROM         Voorraad INNER JOIN
                      Debiteuren ON Voorraad.DebiteurId = Debiteuren.DebiteurId
WHERE     (Voorraad.ModelId = @ModelCode) AND (Voorraad.DeelId = @DeelCode)

-- Voor elke resultrecord van de eerste query doen we dan deze query
SELECT     Velden.Naam, VoorraadVelden.WaardeAM
FROM         VoorraadVelden INNER JOIN
                      Velden ON VoorraadVelden.VeldId = Velden.VeldId
WHERE     (VoorraadVelden.InternetId = @InternetCode) AND (VoorraadVelden.SModelId = @SmodelCode) AND (VoorraadVelden.DebiteurId = @DebiteurCode) AND 
                      (VoorraadVelden.ModelId = @ModelCode) AND (VoorraadVelden.DeelId = @DeelCode)

2. Gecombineerde select
SQL:
1
2
3
4
5
6
 SELECT     Debiteuren.Rode_Naam, Voorraad.InternetId, Voorraad.BijzonderheidInet, VoorraadVelden.WaardeAM, Velden.Naam
FROM         Voorraad INNER JOIN
                      VoorraadVelden ON Voorraad.DeelId = VoorraadVelden.DeelId AND Voorraad.ModelId = VoorraadVelden.ModelId AND 
                      Voorraad.DebiteurId = VoorraadVelden.DebiteurId AND Voorraad.SModelId = VoorraadVelden.SModelId AND Voorraad.InternetId = VoorraadVelden.InternetId INNER JOIN
                      Velden ON VoorraadVelden.VeldId = Velden.VeldId INNER JOIN
                      Debiteuren ON Voorraad.DebiteurId = Debiteuren.DebiteurId 

Methode 1 is erg traag afhankelijk van het aantal resultaten.
Methode 2 is redelijk vlug echter moet er dan zelf nog de dubbele gedeelte van de velden ‘handmatige’ verwijderd worden, wat redelijk gaat zolang deze opvolgend zijn echter bij een sortering lever deze handeling een flinke vertraging op.

Is er een select manier welke ik kan gebruiken of heb ik een fundamentele fout in mijn database zitten?

Heeft uw auto pijn? Ga dan naar de onderdelenlijn
Het bedrijf waar ik met veel plezier werk - Mijn eigen vertrouwde domein


Verwijderd

Begrijp ik het goed dat je een "Delen" tabel hebt met alle onderdelen, en daarbij een "Velden" tabel, om alle eigenschappen van een onderdeel in op te slaan?

Zoals je bijvoorbeeld een schroef hebt in de "Delen" tabel, en in de "Velden" tabel informatie opslaat over het Koptype, Schroefdraad, Grootte, Lengte etc.
Maar van een Spijker wil je weer andere gegevens bijhouden, zoals Materiaaltype, Lengte, Dikte, RechtOfKrom etc.

Begrijp ik het zo goed?

  • mrfatmen
  • Registratie: Februari 2001
  • Laatst online: 13:03
Ja, inderdaad.

Omdat elke product zijn eigen kenmerken heeft.
Bijvoorbeeld bij een portier is het niet belangrijk hoevel cc inhoud de motor heeft.
Maar wel weer of het 2 of 4 deurs is, of er een electrische ramen inzitten.

Heeft uw auto pijn? Ga dan naar de onderdelenlijn
Het bedrijf waar ik met veel plezier werk - Mijn eigen vertrouwde domein


Verwijderd

Ow, dan kan je het misschien beter over een hele andere boeg gooien. Ga eens op zoek naar "Generalization". Check dat alvast op deze pagina: Wikipedia: Class diagram

Wat je dan kan doen is het volgende:

Ieder item heeft bepaalde standaard informatie: categorie, type, fabrikantnaam etc. Bijvoorbeeld:
Materiaal; Schroef; Jansen; ...
Materiaal; Spijker; Pietersen; ...
Materiaal; Bout; Jansen; ...
Gereedschap; Hamer; Fatmax; ...
Gereedschap; Schroevendraaier; Insul; ...

Dat kan je in zo'n tabel opslaan:
code:
1
2
3
4
5
6
Item
--------
Categorie
Type
Fabrikant
...


En dan heb je per type een aantal tabellen in je database.
Bijvoorbeeld de schroef-tabel
code:
1
2
3
4
5
6
7
Schroef
----------
Koptype
Lengte
Dikte
Prijs
...


Dan heb je bijvoorbeeld dit soort schroeven:
code:
1
2
3
4
Koptype  Lengte  Dikte  Prijs
Gleuf    12mm   3mm   0,17
Gleuf    13mm   4mm   0,19
Kruis    14mm   4mm   0,21


Of de moer tabel
code:
1
2
3
4
5
6
Moer
----------
Soort
Maat
Prijs
...


Dan heb je bijvoorbeeld dit soort moeren:
code:
1
2
3
4
Soort       Maat   Prijs
Kartelmoer  4mm   0,24
Kartelmoer  5mm   0,28
Vleugelmoer 5mm   0,32


En dan kan je in die tabellen ook nog opslaan in welk bakje je ze hebt bewaard, hoeveel je er in voorraad hebt en ga zo maar door. Oh, en misschien is het handiger om de fabrikantgegevens niet in de algemene tabel op te slaan, maar juist bij de schroefen, moeren, boutjes zelf.

[ Voor 10% gewijzigd door Verwijderd op 25-08-2008 14:39 ]


  • mrfatmen
  • Registratie: Februari 2001
  • Laatst online: 13:03
Verwijderd schreef op maandag 25 augustus 2008 @ 14:31:
Ow, dan kan je het misschien beter over een hele andere boeg gooien. Ga eens op zoek naar "Generalization". Check dat alvast op deze pagina: Wikipedia: Class diagram

Wat je dan kan doen is het volgende:

Ieder item heeft bepaalde standaard informatie: categorie, type, fabrikantnaam etc. Bijvoorbeeld:
Materiaal; Schroef; Jansen; ...
Materiaal; Spijker; Pietersen; ...
Materiaal; Bout; Jansen; ...
Gereedschap; Hamer; Fatmax; ...
Gereedschap; Schroevendraaier; Insul; ...

<....>
Ik twijfel een beetje of dit praktisch is.
We kunnen momenteel ongeveer 90 verschillende 'kopregel' veldsamenstellingen.
Dit zou dan 90 aparte tabellen opleveren.
Echter z'n er nog wel eens wijzigingen in de samenstellingen.

Ik denk daarom dat mijn oplossing effecienter is.
Omdat er maar een paar tabellen zijn welke alles omschrijven.
Echter zit ik wel met de selectie en uitwerking er van.
Ik wil zo veel mogelijk in een sql commando stoppen. echter als ik een select doe op de voorraadvelden tabel dan krijg ik voor elke onderdeel in voorraad ongeveer 8 records terug.
Is het mogelijk dit al aan de sql kant om te zetten.

SQL routine
SQL:
1
2
3
4
5
6
7
8
SELECT     Delen.Naam AS Onderdeel, Merken.Naam AS Merk, Modellen.Naam AS Model, Velden.Omschrijving AS Veld, VoorraadVelden.WaardeAM AS Waarde, 
                      VoorraadVelden.InternetId AS Id
FROM         VoorraadVelden INNER JOIN
                      Delen ON VoorraadVelden.DeelId = Delen.DeelId INNER JOIN
                      Modellen ON VoorraadVelden.ModelId = Modellen.ModelId INNER JOIN
                      Merken ON Modellen.MerkId = Merken.MerkId INNER JOIN
                      Velden ON VoorraadVelden.VeldId = Velden.VeldId
WHERE     (Modellen.Naam = N'Golf') AND (Merken.Naam = N'VW') AND (Delen.Naam = N'Motor') AND (VoorraadVelden.InternetId = '23')


Resultaat van bovenstaande query
code:
1
2
3
4
5
6
7
8
Deel    Merk     Model   Veld     Waarde  Id

Motor   Vw      Golf     Jaar     1999     23
Motor   Vw      Golf     Prijs    850,00   23
Motor   Vw      Golf     Branstof Benzine  23
Motor   Vw      Golf     Cil.Inh. 1600     23
Motor   Vw      Golf     KM       800000   23
Motor   Vw      Golf     Motornr. AKL      23


Gewenst resultaat
code:
1
2
3
Deel   Merk  Model  Jaar  Prijs    Brandstof   Cil.inh. KM      Motornr  Id

Motor  Vw    Golf   1999  850,00   Benzine     1600     800000  AKL      23


Of is dit een onmogelijk doel?

Heeft uw auto pijn? Ga dan naar de onderdelenlijn
Het bedrijf waar ik met veel plezier werk - Mijn eigen vertrouwde domein


Verwijderd

Wil je dit als output om objecten te vullen, of alleen om rapportages te maken?

Waar je om vraagt is een matrix. En matrix rapporten kan je prima maken met SQL Server Reporting Service, en vast nog met heel veel andere rapport-tools.
Maar waarschijnlijk wil je de data terugkrijgen om je objecten mee te vullen, en ik weet niet precies hoe je dat in matrix-vorm doet.

Breinbreker, deze vraag.

Verwijderd

mrfatmen schreef op zondag 24 augustus 2008 @ 21:25:
In Pick maakt het niet uit dat een record uit ruim 150 velden bestaat waarvan telkens maar een klein aantal gevuld is. In msSQL is dit uiteraard een ander verhaal
Overigens snap ik je opmerking over MS-SQL niet helemaal. Waarom is dat daar een ander verhaal?

Want het is ook een aardig idee om de specifieke artikel-info in 1 grote tabel op te slaan, waarbij je alleen de velden invult die relevant zijn voor het artikel:

code:
1
2
3
4
5
Onderdeel     OndNr  Internet ID  Prijs  Deuren  Uitvoering  Kleur  Brandstof  Cil.Inhoud   Km        Comments
------------  -----    -------    -----   ----     ------    -----   ------    ----------  ----       ---------------
Hoofdsteun    5481      23        23,95     2        Coupe   Zwart     -           -         -        -
Binnenspiegel 9238      32         7,50     3       Hatchb     -       -           -         -        +hb dimmer mooie spiegel
Aircopomp     8832      11       129,00     -            -     -      LPG        1.800     36.000     -

(klap deze tabel uit met het pijltje linksboven de tabel)

Op deze manier kan je alle detail info kwijt op de manier zoals je het wil presenteren, namelijk als 1 record. Je hoeft niet alle info te vullen: voor een hoofdsteun is het niet belangrijk wat de cil.inhoud is, en voor een aircopomp is de kleur niet van belang etc.

Algemene info over het merk van de auto, het model, bouwjaar en welke garage het onderdeel levert kan je dan weer in andere tabellen kwijt.

Eventueel kan je dit ook combineren met de eerste oplossing die ik deed, zodat je misschien niet 1 detail-tabel hebt, maar een aantal. Maar nog altijd veel minder dan de 90 waar de eerste oplossing op uit leek te draaien.

  • mrfatmen
  • Registratie: Februari 2001
  • Laatst online: 13:03
Verwijderd schreef op dinsdag 26 augustus 2008 @ 00:02:

Overigens snap ik je opmerking over MS-SQL niet helemaal. Waarom is dat daar een ander verhaal?

Want het is ook een aardig idee om de specifieke artikel-info in 1 grote tabel op te slaan, waarbij je alleen de velden invult die relevant zijn voor het artikel:
Ik dacht altijd dat als je velden defineerd maar deze niet gebruikt deze toch ruimte innemen.
Maar als ik een detailtabel aanmaak van ongeveer 70 velden.
En per record worden er maximaal 12 gebruikt kan dit geen kwaad voor performance?
Dat zal dan de oplossing zijn.

Heeft uw auto pijn? Ga dan naar de onderdelenlijn
Het bedrijf waar ik met veel plezier werk - Mijn eigen vertrouwde domein


  • bat266
  • Registratie: Februari 2004
  • Laatst online: 08:54
Het is ook erg nadelig voor de performance om elke x al die velden bij elkaar te zoeken voor onderdeel x. Een combinatie van beiden kan dan een mooie tradeof opleveren.

Better to remain silent and be thought a fool then to speak out and remove all doubt.


Verwijderd

mrfatmen schreef op dinsdag 26 augustus 2008 @ 07:42:

Ik dacht altijd dat als je velden defineerd maar deze niet gebruikt deze toch ruimte innemen.
Maar als ik een detailtabel aanmaak van ongeveer 70 velden.
En per record worden er maximaal 12 gebruikt kan dit geen kwaad voor performance?
Dat zal dan de oplossing zijn.
Ik ben het eens met wat bat266 zei.

Verder maakt het qua performance allemaal niet zo veel uit als je maar 1000 tot 100.000 onderdelen hebt in je database en je deze wilt gebruiken voor een website.
Als het om miljoenen records gaat waarmee je queries gaat uitvoeren die binnen miliseconden een resultaat moeten teruggeven, dan wordt het misschien een ander verhaal.

Maar als ik van een afstandje naar jouw situatie kijk, dan zijn begrijpelijkheid en onderhoudbaarheid van de oplossing belangrijker dan performance in miliseconden.
Pagina: 1