Avatar billede tubber Juniormester
05. februar 2010 - 10:20 Der er 18 kommentarer og
1 løsning

Opbygning af database

Jeg har oprettet en database i MySQL.

Nu skal jeg ha oprettet tabeller, men kan ikke lige helt overskue hvad der vil være smartest, da jeg ikke har så meget erfaring i hvordan den strukturerers.

I min database skal jeg ha følgende:
-Gruppe (Det er et statisk antal, når de er oprettet vil der ikke komme flere)
-Type (Der vil løbende komme flere typer).
-Art (Der vil være forskellige arter som er tilhørende en type, en art kan forkomme under flere typer).
-Antal (Mængden af en art).
-Beskrivelse (En tekst af ukendt længde der beskriver en type).

Som udgangspunkt vil jeg mene det er smartest at lave hver Gruppe som en tabel, men så er det problemet opstår.

Den direkte løsning vil være at lave en Type som primær post, og så ellers bare hver art og antal som sekundære data, evt. bare putte art og antal i samme felt, og så beskrivelsen i et felt.
Men her ser jeg så en ulempe ved at jeg skal lave eksempelvis 100 felter for at være sikker på der er felter nok til at indtaste data i.

Et andet udgangspunkt kunne være at lave hver art som tabel, og så lægge type ind som en værdi i et felt med en tilhørende antal.
Og så have en tabel der hedder gruppe hvor jeg igen henviser med type og beskrivelse, her ser jeg så problemet at hver søgning kræver den kører alle tabeller igennem for at chekke om der er en værdi.

Som sagt kan jeg ikke lige se hvad der er smartest, og der kan sagtens findes en mere hensigtsmæssig løsning, så eftersøger her nogle forskellige forslag med fordele og ulemper.

På forhånd tak.
Tubber

PS: Skal lige sige at data skal trækkes fra en ekstern kilde over internettet.
Avatar billede keysersoze Guru
05. februar 2010 - 10:41 #1
Mine umiddelbare tanker er at du skal sætte dig ind i normalisering (se fx en smule om det her http://www.eksperten.dk/guide/234) samt overveje fx mange-til-mange til mange tabeller (altså tabeller som sammensætter fx id'er fra type og id'er fra gruppe).

Det er meget sjældent det kan betale sig at tænke i alternative tabel-opbygninger for at spare noget på forespørgslerne.
05. februar 2010 - 11:13 #2
En langt bedre indføring i den grundlæggende databaseopbygning findes i denne guide skrevet af arne_v:

http://www.eksperten.dk/guide/55

... og NEJ - der er ingen lette genveje til en fornuftig databasestruktur, og ikke noget der kan laves smartere af hensyn til forespørgsler!
Avatar billede tubber Juniormester
05. februar 2010 - 11:49 #3
Nu har jeg læst begge artikler igennem, men syntes det virker som noget unødvendigt, da ALLE data er statiske, når de først er indtastet så KAN der ikke komme ændringer.

Så umiddelbart ud fra det jeg har læst vil den nemmeste løsning være en tabel til hver gruppe og så et felt til hver datatype.

For når jeg så skal lave min søgning kan jeg bare kører den gruppe igennem der skal søges i, og derefter trække det ene recordset ud.

Eller er jeg helt ved siden af her ?
Avatar billede keysersoze Guru
05. februar 2010 - 13:17 #4
statiske data eller ej - den rigtige løsning vil i mine øjne stadig være en korrekt database-opbygning. Dels vil din database få bedst performance og vedligeholdelse på den måde, dels vil forespørgsler lettest kunne opbygges og sidst men ikke mindst ved man ikke hvad der sker i fremtiden fx med udviddelse af data eller selve databasen eller hvis du fx får brug for at mappe databasen direkte over til nogle objekter i en applikation.

Selvfølgelig bestemmer du selv hvad du vil gøre - men med en for alternativ opbygning risikerer du bare at støde på problemer en gang i fremtiden hvorimod en rigtig opbygning altid vil kunne bruges.
05. februar 2010 - 20:40 #5
tubber, du er paa vildspor (jeg er enig med mine med-indlaeggere.)  Men vi kan vel finde en bedre maner hvis du vil fortaelle lidt mere om hvad dine data representerer og hvad du vil opnaa. 

Jeg proevede at forestille mig hvad strukturen kunne vaere i dine grupper, typer, og arter.  Jeg lavede et konkret eksempel med madlavning (maaske fordi jeg er ved at vaere sulten.)  Jeg forestiller mig at grupperne er vegetarretter og koedretter.  Typerne er saa retter, for vegetarretter suffle og ommelet, for koedretter grydeboef og oksesteg.  Arterne er saa ingredienser saasom oksekoed, kartofler, maelk og mel, og jeg forestiller mig at der til suffle gaar 300 gram mael og 200 gram mel, til ommelet 300g kartofler og 100g maelk, til grydeboef 350g oksekoed og 100g mel, og til oksesteg 500g oksekoed og 300g kartofler.

I saa fald ville jeg lave en tabel over grupper og en tabel over arter.  Saa en tabel Type med tre felter, typens navn, den gruppe typen hoerer til, og en beskrivelse.  Og til slut en Art_i_type tabel hvor jeg viser alle kombinationer af typer og arter og hvor mange af en art der gaar til en type.  Her er mine tabeller sammen med data:

GRUPPE
Navn
Vegetarretter
Koedretter

ART
Navn
oksekoed
kartofler
maelk
mel

TYPE
Navn,    Gruppe,      Beskrivelse
suffle    vegetarretter Dette er en beskrivelse af suffle
ommelet  vegetarretter Her staar noget om ommelet
grydeboef koedretter    Grydeboeffens serenade
oksesteg  koedretter    En okse maa bokse

Art_i_type
Type,      Art,      Antal
suffle    maelk    300
suffle    mel      200
ommelet    kartofler 300
ommelet    maelk    100
grydeboef  oksekoed  350
grydeboef  mel      100
oksesteg  oksekoed  500
oksesteg  kartofler 300

Med de tabeller og ved hjaelp af SQL kan jeg finde alle de oplysninger i alle de opstillinger som du kan have behov for, og du kan skabe et ubegraenset antal typer og arter (og ogsaa grupper hvis du vil) uden at skal lave tabeller med mindst 100 felter for at have nok o.s.v.

Selvfoelgelig er det ikke grydeboeffer og kartofler det drejer sig om, men hvad er det saa?  En gruppe kan uden tvivl have mange typer, men kan en type, som i dette eksempel, kun tilhore en enkel gruppe?
Avatar billede tubber Juniormester
06. februar 2010 - 11:39 #6
Se nu ligner det noget forståeligt og jo det er rent faktisk noget med mad :P

Selv om jeg syntes den Tabel der hedder art for mig ser lidt unødvendig ud så giver det nu meninng :)

Så er det vel bare igang :) Så må jeg jo læse lidt mere om queries og joins i selve databasen senere :)

Så hvis i alle smidder svar vil jeg prøve at dele point ud :)
06. februar 2010 - 12:35 #7
Jeg var glad for at mit indlaeg var til nytte.  Relational databases og data normalisering er ikke saa svaert, mest 'common sense,' naar foerst man er kommet ind i det, men det kan vaere lidt krikket at faa hovedet vendt den rigtige vej.  Jeg haabede at et konkret, skoent fiktivt, eksempel ville hjaelpe (hvad du siger det gjorde.)

Et par yderligere kommentarer (som jeg ikke inkluderede i mit foerste indlaeg for ikke at goere det for indviklet:)

(1)  I virkeligheden vil du i hver tabel inkludere et felt mere, et numerisk id felt.  Altsaa for eksempel:

GRUPPE
id navn
1  vegetarretter
2  koedretter

Saa vil underordnede tabeller henvise til id-numre i stedet for navne i overordnede tabeller, for eksempel:

TYPE
id navn  gruppe_id  beskrivelse
1  suffle 1          Dette er en beskrivelse...

Men jeg brugte navne i stedet for id-numre fordi det er nemmere for mennesker (skoent svaerere for komputers) at overskue.

(2)  Tabellerne GRUPPE og ART kan godt se lidt overfloedige ud.  Deres formaal er at standardisere de gruppe- og art navne du bruger for at undgaa besvaer med senere at soege i tabellerne.  Hvis du, for eksempel, vil lave en oversigt over gruppenavn og typenavn paa alle vegetarretter saa laver du en SQL-query paa to tabeller saaledes:

SELECT GRUPPE.navn, TYPE.navn FROM GRUPPE JOIN TYPE ON GRUPPE.id = TYPE.gruppe_id

Komputeren laver internt en ny tabel med alle kombinationer af raekkerne i de to tabeller.  Da der er to raekker i GRUPPE og fire raekker i TYPE faar den nye tabel otte raekker.  Dernaest beholder komputeren de raekker hvor id i GRUPPE er lig med gruppe_id i TYPE og smider resten af raekkerne vaek. De resulterende raekker har seks felter, GRUPPE.id, GRUPPE.navn, TYPE.id, TYPE.navn, TYPE.gruppe_id, TYPE.beskrivelse.  Komputeren beholder nu de to felter du sagde du ville have, GRUPPE.navn og TYPE.navn, og smider resten vaek, og nu har du det resultat du soegte.  Men hvis nu nogen ved fejltagelse har skrevet 7 i stedet for 1 som gruppe_id i TYPE saa vil der gaa gak i querien.  Derfor skal du lave en saakaldt fremmednoegle fra TYPE.gruppe_id til GRUPPE.id.  Saa vil komputeren afvise forsoeg paa at indsaette ikke-bestaaende gruppe_id'er i TYPE.  Ligeledes skal tabellen ART_I_TYPE have disse felter:
id type_id art_id antal
1  1      3      300
2  1      4      200
o.s.v., og med fremmednoegler fra type_id til TYPE.id og fra art_id til ART.id.

Held og lykke med dit forehavende.
Avatar billede tubber Juniormester
07. februar 2010 - 11:23 #8
Lige et kort spørgsmål, nu hvor jeg har læst Arne_v artikel igen, og forstår lidt mere efter Christians forklaring, Så skal jeg bruge Type som PK og så have et felt i de andre tabeller med PK som FK, for at have et unikt FK som kan bruges i queries ?
Avatar billede keysersoze Guru
07. februar 2010 - 11:30 #9
Alle tabeller bør have en PK - og det mest optimale ud fra Christians forslag er at sætte kolonnen ID til autonummering og primærnøgle. Din primærnøgle kan du nu bruge som FK i de øvrige tabeller der på en eller anden måde skal referere til en anden tabel - og det er netop denne fremmednøgle, der binder det hele sammen i en relationsdatabase.
07. februar 2010 - 12:15 #10
Tubber, jeg er enig med keysersoze.  Der er i princippet ikke noget i vejen for at bruge TYPE.navn som primaerkoegle, men det er almindelig brug at lave et numerisk ID felt og de gaengse systemer saa som mysql synes at vaere optimeret til dette.  Du kan saa saette TYPE.ID til autonummering. (Jeg undlod i #7 at snakke om primaernoegler for ikke at komme med det hele paa en gang,men nu er du ved selvstudie kommet et trin videre.)
Avatar billede tubber Juniormester
07. februar 2010 - 13:01 #11
Ved godt der skal være en primær nøgle i alle tabeller, men for at have noget 100% unikt som FK mener jeg det er Type der er den bedste at bruge, da der kan komme typer med samme navn under de forskellige brugere.
Avatar billede keysersoze Guru
07. februar 2010 - 13:17 #12
Jeg føler mig ikke helt tryg ved at du siger "Type" - for enten misforstår du eller også kan jeg bare ikke helt følge det du skriver.

I tabellen "Type" sætter du "Id" til at være primærnøgle og det samme gør du i tabellen "Art". Så kan der opstå nogle forskellige muligheder, fx kan "Art" tilhøre én "Type og så vil dine tabeller se således ud;

TYPE
Id (PK)
Navn

ART
Id (PK)
TypeId (FK)
Navn

Og en anden mulighed er at "Art" kan ligge i flere forskellige "Typer" og så vil dine tabeller se sådan ud;

TYPE
Id (PK)
Navn

ART
Id (PK)
Navn

JOINTYPEART
TypeId (FK)
ArtId (FK)
Avatar billede tubber Juniormester
07. februar 2010 - 13:50 #13
Nu har jeg oprettet en tabel, men er ikke sikker på det med nullværdi og type, har sat int og text er de gode nok ?

SQL-forespørgsel:
CREATE TABLE `gruppe` (
`gr_ID` INT NOT NULL AUTO_INCREMENT ,
`gr_NAVN` TEXT NOT NULL ,
`id_FK` INT NOT NULL ,
PRIMARY KEY ( `gr_ID` )
) TYPE = MYISAM ;
Avatar billede keysersoze Guru
07. februar 2010 - 14:16 #14
Det ser fint ud - men navnet på din FK er i mine øjne intetsigende, hvad vil du fx gøre den dag en tabel skal have fremmednøgler til to andre tabeller? Brug sigende navne.
Avatar billede tubber Juniormester
07. februar 2010 - 17:22 #15
Ok nu har jeg fået strikket 3 tabeller sammen:

op_ID (int) (PK og FK i andre tabeller)
op_NAVN (text)
op_beskriv (text)

gr_ID (int) (PK)
gr_NAVN (text)
id_FK (int) (FK = op_ID)

va_ID (int) (PK)
va_NAVN (text)
va_ANTAL (int)
va_MAAL (text)
id_FK (FK = op_ID)

Alle faktorer vil ALTID være bestemt af op_ID, derfor det id_FK.
va_ mener jeg umiddelbart ikke er til at splitte mere op, da va_NAVN altid vil ha et antal og et mål (har splittet antal og mål så der kan beregnes på det).

Ser det fornuftigt ud ?
07. februar 2010 - 17:57 #16
Det er lidt svaert at gennemskue fordi du bliver ved med at vaere meget abstrakt.  Jeg proevede at svare i konkrete vendinger fordi jeg mente at det ville fremme kommunikationen, og jeg havde regnet med at du ville svare i samme aand, men det synes du aabenbart ikke, saa for at svare maa jeg i gang med at gaette endnu en gang.

Jeg gaetter paa at den tabel med op_ID o.s.v. indeholder opskrifter der hver har en id, et navn, og en beskrivelse.  Til hver opskrift gaar der et antal varer som du har i tabellen med va_id o.s.v.  Tabellen indeholder varens navn, maengden der gaar til, og maalet, for eksempel 250 gram mel eller 3 stk bananer.  Saa fordi hver linie i va tabellen referer til en enkelt opskrift men hver opskrift kan have mange varer noedigt er det korrekt at va har en fremmednoegle til op_id.

Saa vil jeg gaette paa at tabellen med gr_id indeholder grupper med gruppenavn.  Du synes ogsaa at ville have fremmednoegle fra gr til op_id.  Det ville vaere korrekt hvis det er saaleldes at hver opskrift kan inddeles i adskillige grupper og en gruppe kun kan hoere til en opskrift.  Jeg ville have troet at det var omvendt, at du definerer et antal grupper af opskrifter saaledes at en gruppe indeholder adskillige opskrifter men en opskrift kun hoerer til en gruppe.  Hvis det er tilfaeldet saa skal du vende fremmednoeglen om saaledes at op-tabellen skal indeholde en gr_id med fremmednoegle til gr_id.
Avatar billede tubber Juniormester
07. februar 2010 - 18:35 #17
Det er korrekt med at Grupper kan indeholde flere opskrifter, og at en opskrift kun kan være i en gruppe.

Og her er det så når jeg trykker på en knap skal den hente alle opskrifter og putte dem i forskellige faner (en til hver gruppe).

Når man så vælger en opskrift i den enkelte gruppe skal den så hente opskriften (her vil det så ikke være relevant at hente gruppen ind).

Så det du siger er at det vil være nemmest hvis jeg laver mine PK og FK som følge:

gr_ID (PK)

op_ID (PK)
op_FK (gr_ID)

va_ID (PK)
va_FK (op_ID)
07. februar 2010 - 19:22 #18
Jep!  Precis.

Naar du "trykker paa knappen" saa gaetter jeg paa at du vil have et resultat der viser alle grupper og for hver gruppe navnene paa alle opskrifterne.  Det bliver, med dine tabeller og med pk/fk som i #16/#17 til saadan en query:  SELECT gr_NAVN, op_NAVN FROM GRUPPE JOIN OPSKRIFT ON GRUPPE.gr_ID = op_gr_ID

Naar du saa vaelger en enkelt opskrift gaetter jeg paa at du vil have opskriftens navn plus alle varerne med antal og maal.  Saa hvis du har opskriftens navn i en variabel $opskrift saa bliver querien:  SELECT op_NAVN, va_NAVN, va_ANTAL, va_MAAL FROM OPSKRIFT JOIN VARE ON OPSKRIFT.op_ID = VARE.va_id WHERE VARE.va_NAVN = '$opskrift'

Saa vil jeg ioevrigt mene at tiden er ved at vaere inde til at afslutte traaden.  Du stillede et spoergsmaal til Ekspertens medlemmer og fik et antal indlaeg.  Du stillede saa yderligere spoergsmaal i flere runder.  Jeg har forsoegt at svare saa uddybende som jeg kan og jeg har nu udtoemt min viden.  Det boer nu ikke blive til en privat konversation mellem os to.  Proev det af (som jeg kan se du har vaeret i gang med). Hvis du saa loeber ind i nye problemer saa maa vejen frem vaere at fremlaegger disse i et nyt spoergsmaal til Ekspertens medlemskab som helhed hvoraf nogle sikkert er klogere end jeg.  (Hvis det kommer til nye spoergsmaal vil jeg nok foreslaa at du beskriver helt konkret hvad du har, hvad formaalet er, og hvor precis du er gaaet i staa.)

Under alle omstaendigheder held og lykke med den videre fremgang.
Avatar billede tubber Juniormester
07. februar 2010 - 19:29 #19
Nej :) så har jeg forstået det og du giver mig endda svar på et kommende spørgsmål når jeg kommer igang med programering

mange tak for tålmodigheden :)

eftersom de andre ikke har lagt nogle svar får du dem alle

Håber det er ok
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Computerworld tilbyder specialiserede kurser i database-management

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester