Avatar billede alex15 Nybegynder
25. januar 2010 - 18:26 Der er 8 kommentarer og
1 løsning

Kalender funktion - hvordan bør data gemmes?

Hej alle,

Jeg skal i gang med at lave en kalender funktion til min side.

Den skal fungere på følgende måde:

While(){

//Henter en række medlemmere
// X = Udlejet den bestemte dag

              Mandag    Tirsdag    Onsdag    Torsdag
1. Lars        x              x              x
2. Henrik                    x              x
3. Peter

}

Forstået på den måde, at når der kommet et x, så har Lars lejet et produkt den pågældende dag.

Hvordan bør jeg gemme disse data i min database?

Mit forslag:
Bør der for Lars gemmes én data for hver af de dage mellem mandag og onsdag - Så der i databasen er 3 linjer.

Så når man laver ovenstående while(), så går den for hver dag hos Lars, Henrik og Peter ind i databasen og ser om den pågælende person har lejet et produkt den bestemte dag, og hvis dette er tilfældet skriver et "x"?

Eller findes der en smartere og mindre data krævende måde at gøre det på? - For mig virker den her måde nemlig lidt data tung, hvis dette skal gøres for 50 person?

På forhånd mange tak

Alex
25. januar 2010 - 19:28 #1
Der er en mange-til-mange relation mellem personer og lejedage.  Du skal derfor bruge tre tabeller:

Person(id INT, navn VARCHAR(??))

Dag(id INT, navn VARCHAR(10))

PersonDag(id INT, pID INT, dID INT)

I dit tilfaelde ville Persontabellen faa disse vaerdier:

id navn
1 'Lars'
2 'Henrik'
3 'Peter'

Dag tabellen vil faa disse vaerdier:

id navn
1 'mandag'
2 'tirsdag'
3 'onsdag'
4 'torsdag'

Og din PersonDag tabel faar disse vaerdier:

id pID dID
1  1  1
2  1  2
3  1  3
4  2  2
5  2  3

Det er 'quick and dirty.'  Du vil formentlig vaelge en anden maade at representere dine dage saa du kan holde rede paa en laengere periode end en enkelt uge, men paa denne maade er din database normaliseret og du kan soege paa den.  Hvis du for eksempel vil have alle Lars's lejedage: 

SELECT p.navn, d.navn
FROM Person p JOIN PersonDag pd ON p.id = pd.pID
JOIN Dag d ON pd.dID = d.id
WHERE p.navn = 'Lars'

Eller hvis du vil have navnene paa dem der har lejet Onsdag:

SELECT p.navn
FROM Person p
JOIN PersonDag pd ON ON p.id = pd.pID
JOIN Dag d ON pd.dID = d.id
WHERE D.navn = 'ONSDAG'
Avatar billede Slettet bruger
25. januar 2010 - 19:34 #2
Jeg ville mene den smarteste metode er den du beskriver, hvis jeg forstår dig rigtigt.
Du har en tabel med personer (id, navn)
Og en tabel med hvem der har lejet et produkt og hvornår (id, person_id, dato)
Så det du gør er først at loope din person-tabel igennem, ud for hver person tjekker du så de pågældne dage imod din "hvem-har-lejet-noget"-tabel og hvis der bliver fundet nogle matches plotter den X's ind ud for de forskellige dage.


Angående dine bekymringer for resource forbruget af den metode, vil jeg lige pointerer at databaser er specialister til at udfører sådanne opgaver hvis dine tabeller er opsat ordentligt.
Avatar billede alex15 Nybegynder
25. januar 2010 - 20:53 #3
Tak for godt input.

Hvis man nu forstiller sig at en person (Lars) lejer noget i perioden fra 21/01/10 - 23/01/10.

Så ville man blive nød til at skrive følgende ind i databasen:

Oprettelse af personen i databasen: (Gøres én gang)
Person(id INT, navn CHAR(50))
1, Lars

Oprettelse af produkt i databasen: (Gøres én gang)
Person(id INT, produkt INT(50))
1, Computer

Oprettelse af lejeaftale i databasen:
Person(id INT, produkt INT, navn CHAR(50), dato timestamp)
1, Computer, Lars, 21/01/10
2, Computer, Lars, 22/01/10
3, Computer, Lars, 23/01/10

Så kunne man vel lave et scrip som startede fra mandag og sluttede søndag i uge 3.

Altså således:

While(//Brugerne){

  While(//uge dagene i uge 3){

      if(//dato fra lejeaftale == dato){ //x }

  }

}

Dette ville så være den bedste måde at gøre det på ikke? - Synes dog at den virker ret data tung, man der er jo nok ikke andre måder man kan gøre det på.

"vil jeg lige pointerer at databaser er specialister til at udfører sådanne opgaver hvis dine tabeller er opsat ordentligt."

Men er det ikke begrænset hvor meget anderledes de kan lave i denne her metode?
25. januar 2010 - 21:23 #4
alex15, du synes at udvide problemet, du har ikke alene forskellige personer men ogsaa forskellige genstande der kan lejes, og det drejer sig ikke om enkeltdage men om perioder, for eksempel Lars lejer computer nummer 1 fra 21/1/2010 til 23/1/2010.

Jamen saa ville jeg lave en Person-tabel som sagt ovenfor med id og navn, og saa en Genstand-tabel med id og navn/beskrivelse og saa Leje-tabellen der bestaar af de foelgende felter:  id, p-ID, g-ID og saa en startdag og en slutdag.  Saa hvis Lars med p-ID 7 lejer computer1 med g-ID 12 fra 21/1/2010 til 23/1/2010 saa skriver du den foelgende query:  INSERT INTO Lejetabel(p-ID, g-ID, startdag, slutdag) VALUES(7, 12, '21-01-2010', '23-01-2010')  Ingen behov for en while loekke.

Hvis du, som du synes at vaere inde paa, vil lave det med en script fra en hjemmeside saa vil din HTML form have input felter for lejer, genstand, start- og slutdag og din kode bliver noget i retning af:  <?php if($_FORM['submit'] mysql_query = "INSERT INTO Lejetabel(p_ID, g_ID, startdag, slutdag) VALUES $lejer, $genstand, '$startdag', '$slutdag')?>

Hvis udlejningsforetningen udvider sig saa skal systemet nok udbygges med tabeller og kode til at sikre at man ikke lejer den samme genstand ud to gange paa samme dag, men det ligger udenfor det nuvaerende spoergsmaal.
Avatar billede alex15 Nybegynder
25. januar 2010 - 21:37 #5
Fik nok ikke lige forklaret mig ordenligt nok i starten så, det undskylder jeg for. Men det virker til at du har forstået hvor jeg vil hen.

Okay, den måde kunne man selvfølgelig også gøre det på.

Men på hvordan ville du så tjekke for om personen har udlejet det på den pågældende dag?

While(//Brugerne){

  While(//uge dagene i uge 3){

      if(//dato fra lejeaftale > dato && //dato fra lejeaftale < dato){ //x }

  }

}

Så som jeg ser det, ender jeg stadigvæk ud i samme problemstilling.

Målet er at følgende skal komme frem:

Vis alle personer som der er registeret:

Lars
Henrik
Erik

Oven for dem, skal der være ugedagene, og så skal de vises i hvilke dage de pågældende personer har lejet et produkt.

Eller er det mig som der har misforstået det?
25. januar 2010 - 23:35 #6
Du skal skelne mellem hvordan du slaar dine data op i databasen og hvordan du traekker dem ud og presenterer dem.  Overskriften paa spoergsmaalet var "hvordan boer data gemmes?"  Svaret er at du boer gemme dataerne i overensstemmelse med deres struktur, ikke i overensstemmelse med hvordan du senere vil presentere dem.  En saakaldt normaliseret relationel struktuur hvor hver "slags" data sidder i en tabel for sig med links imellem gaar man ikke fejl af.  Fra saadan en struktur kan du traekke data ud og presentere dem paa alle taenkelige maader og det er nemt at gemme nye data.  Saa til spoergsmaalet om hvordan du skal gemme dine data er svaret det jeg har givet.

Saa siger du:  "hvordan ville du saa tjekke for om personen har udlejet det paa den paagaeldende dag?"  Mener du hvordan vil jeg tjekke, for eksempel, om Lars har lejet computer1 21/1/2010?  Der er en kort query hvis du kender pID for Lars og gID for computer1 og en laengere query hvis du ikke kender eller ikke vil bruge id'erne.

Den korte (Lars er pID7 og computer1 er gID12)

SELECT * FROM PersonGenstand WHERE pID = 7 AND gID = 12 AND '21-01-2010' BETWEEN startdate AND enddate

Hvis du faar et svar (hvis queryen returnerer en eller flere raekker) saa lejer Lars computer1 21/1/2010.  Hvis queryen returnerer 0 raekker saa lejer Lars den ikke den dag.

Den lange:

SELECT * FROM Person p
JOIN PersonGenstand pg ON p.id=pg.pID
JOIN Genstand g ON pg.gID = g.id
WHERE p.navn = 'Lars' AND g.navn = 'computer1'

Hvordan du skal udskrive det paa en hjemmeside, og hvordan du laver en oversigt over hvilke personer der har lejet en eller flere genstande hvilke ugedage skal jeg komme tilbage til i morgen.  Der skal jeg lige have funded php'en frem og det er sengetid.
Avatar billede alex15 Nybegynder
26. januar 2010 - 10:11 #7
Okay ja, men tak for dit svar til det spørgsmål så, du må undskylde hvis jeg kludre lidt rundt i det. Men som oftes før fører et svar, ofte til en ekstra spørgsmål.

Arh, havde slet ikke tænkt på denne 'BETWEEN' metode.

Hvad skulle være grunden til at være den ene frem for den anden? - For mig virker det da smartest blot at avende 'den korte'. Men det skyldes måske også blot at jeg aldrig har arbejdet med 'JOIN' før?

Tak fordi du gider bruge så lang tid på det. Sætter jeg stor pris på.

Ser frem til at høre fra dig igen. - Dette er en stor hjælp for mig.
26. januar 2010 - 12:47 #8
Tak for roserne.

Jeg sluttede i gaar med at konstatere at du synes at oenske en opstilling hvor for en uge du viser hvilke personer der lejer en eller flere genstande dag for dag, for eksempel:

navn mandag tirsdag onsdag
Lars            x    x
Jens  x              x

og jeg paatog mig at komme med et forslag.  Det har jeg nu gjort, og for at teste det har jeg lavet en lille hjemmeside http://christianjorgensen.be/alex.php og en mini-database med tre tabeller, alexPerson, alexPersonGenstand, og alexGenstand.  Paa hjemmesiden har jeg saa lavet en form hvor du kan indsaette den foerste og den sidste dag i ugen du soeger.  Paa grund af den maade min version af mysql behandler datoer skal du indfoere dem som yyyy-mm-dd, for eksempel 2010-01-18.  Saa ville jeg helst have fundet en mysql query der gav de rigtige oplysninger paa en gang, men det kraever en mysql procedure og det stoetter min mysql version ikke.  Saa jeg har foerst lavet en query der finder navnene paa de personer der har lejet en eller flere genstande i den paagaeldende uge.  De navne putter jeg i en array.  Saa for hvert navn laver jeg en query for hver dag i ugen.  Jeg bruger mysql funktionen ADDDATE saa jeg spoerger om begyndelsdagen plus 0 dage, plus 1 dag, o.s.v.  Forneden viser jeg min kode og de tabeller jeg bruger.  For ugen 18-24 januar fik jeg, med mine data, denne opstilling.  Er det hvad du taenkte paa? (Det er forvraenget her, kik selv paa hjemmesiden.)

Navn:  mandag tirsdag onsdag torsdag fredag loerdag soendag
Jens                  X      X      X      X      X
Lars  X      X      X              X 
Per                                                X

Det kan der goeres meget mere ud af, for eksempel at man kan vaelge vilkaarlige data, men det var ikke spoergsmaalet.

Kan vi slutte nu og lukke spoergsmaalet?  Jeg mener at jeg har besvaret dit spoergsmaal.

Her er koden og tabellerne:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
  <title></title>
</head>

<body>
<?
$link = mysql_connect ('christianjorgensen.be.mysql', 'christianjoygen', 'dnyBKKbe') or die(mysql_erorr());
mysql_select_db('christianjoygen') or die('Could not select database');
if($_POST['submit'])
{
  $start = $_POST['start'];
  $end = $_POST['end'];
  echo "<table>";
  echo "<tr><td>Navn: </td><td>mandag</td><td>tirsdag</td><td>onsdag</td><td>torsdag</td><td>fredag</td><td>loerdag</td><td>soendag</td></tr>";
  $navne = mysql_query("SELECT navn FROM alexPerson p JOIN alexPersonGenstand pg ON p.id = pg.pID WHERE start <= '$end' AND end >= '$start' GROUP BY navn") or die(mysql_error());
  while($row=mysql_fetch_array($navne)) $navneliste[] = $row['navn'];
  for($i=0; $i<count($navneliste); $i++)
  {
    echo "<tr><td>$navneliste[$i]</td>";
    for($j=0; $j<7; $j++)
    {
      $dato = mysql_query("SELECT 'x' FROM alexPerson p JOIN alexPersonGenstand pg ON p.id=pg.pID WHERE p.navn = '$navneliste[$i]' AND ADDDATE('$start', $j) BETWEEN start AND end") or die(mysql_error());
      echo "<td>";
      if(mysql_num_rows($dato)>0) echo "X";
      echo "</td>";
    }   
    echo "</tr>";
  }
  echo "</table>";
}
mysql_close($link); 
?>
<br/>
<form method="POST" action= <?print $_SERVER["PHP_SELF"]?>>
<table>
<tr><td>start: <td/><input type="text" name="start" /></tr>
<tr><td>end: <td/><input type="text" name="end" /></tr>
<tr><td></td><td><input type="submit" name="submit" value="submit" /></td></tr>
</table>
</form> 
</body>
</html>

alexPerson
id  navn 
      1 Lars
      2 Hans
      3 Jens
      4 Per

alexPersonGenstand
      id  pID  gID  start  end 
      4 1 2 2010-01-18 2010-01-20
      2 1 3 2010-01-22 2010-01-22
      3 4 1 2010-01-24 2010-01-25
      1 3 3 2010-01-20 2010-01-24

alexGenstand
id  navn 
      1 computer1
      2 computer2
      3 flagstang
      4 tandem
Avatar billede alex15 Nybegynder
26. januar 2010 - 13:23 #9
Endnu engang et meget fornemt og brugeligt svar. Også fedt at du lige vedhæftet koderne, så jeg kan se hvordan du har gjort det.

Men det vil jeg lige selv ligge og rode lidt med, burde ikke blive noget problem. - Også mht. til de forskellige ændringer mv.

Endnu engang tak for hjælpen, og den tid du har gidet bruge på det. Sætter jeg stor pris på.

Hav en forsat god dag.

Alex




Spørgsmål lukket.
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
Vi tilbyder markedets bedste kurser inden for webudvikling

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