• Das Erstellen neuer Accounts wurde ausgesetzt. Bei berechtigtem Interesse bitte Kontaktaufnahme über die üblichen Wege. Beste Grüße der Admin

3-dimensionales array - MySQL

badenixe63

New member
Hallo Leute,

ich sitze gerade an einem Problem und habe keine Ahnung wie es funktionieren koennte...

ich moechte gerne in einer mysql Tabelle festhalten, ob jemand an einem tag anwesend war oder nicht. Ich habe schon eine Tabelle mit Usern, in der name und addresse usw. sind.

aber wie kann ich da jetzt die anwesenheit abspeichern ? vllt. mit so ner art 3 dimensionalem array?
$anwesenheit[jahr][monat][tag] = true/false;

aber wie kriege ich das in die tabelle ?

vllt. hat ja auch noch jemand ne ganz andere idee ?
 
Zuletzt bearbeitet:
mal ganz grob:
Code:
CREATE TABLE `anwesenheit` (
`person` INT UNSIGNED NOT NULL,
`datum` DATE NOT NULL,
`anwesend` TINYINT(1) UNSIGNED NOT NULL,
PRIMARY KEY (`person`, `datum`)
) ENGINE = MYISAM;
wenn du dann ein array hast wie du geschrieben hast kannste die daten recht leicht einfügen

PHP:
$rows = array();
$person = 1; // id von der person zu der das anwesenheits-array gehört
foreach($anwesenheit AS $jahr => $monat) {
	foreach($monat AS $tag => $status) {
		$date = $jahr.'-'.$monat.'-'.$tag; // format muss sein: yyyy-mm-dd
		$answesend = $status ? 1 : 0;
		array_push($rows, "($person, '$date', $anwesend)");
	}
}

$sql = 'INSERT INTO `anwesenheit` (`person`, `datum`, `anwesend`) VALUES '.implode(', ', $rows);
mysql_query($sql) OR die(mysql_error());
codes sind ungetestet
 
Ist aber ein bißchen überflüssig beides zu speichern, da ich aus den Daten über die Anwesenheit auch die Abwesenheit schließen kann.
Auch deine PHP Datenstruktur ist ein wenig aufgebläht. Sinnvoller wäre es die Datumswerte direkt in ein Array zu speichern und dieses zu sortieren (mit mysql) und dann mit binärer Suche zu gucken ob ein Datum enthalten ist oder nicht.

Binäre Suche – Wikipedia
Binäre Suche – Wikipedia
 
ok, binaere Suche klingt gut, aber wie speichere ich das dann genau in mysql ab ?

ein feld in der user-tabelle in dem einfach nur aneinander gereihte datumswerte stehen, mit ; getrennt ? oder ne zweite Tabelle aufmachen so wie skooli gesagt hat ? und wer macht die binaere suche ? Mysql oder PHP ?

ach ja, ich moechte das ganze hinterher monatsweise ausgeben...
 
Zuletzt bearbeitet:
ok, aber es sind taeglich um die 50-100 Leute dort,

die tabelle wird ja riesig bei so viel anwesenheit... das ganze soll ja irgendwie auch fuer die "Zukunft" gestrickt sein, und in ein paar jahren habe ich dann eine Monstertabelle in der jeder Query ziemlich lange dauern wird oder ?

und die mache ich die von ZeitGeist beschriebene Binaersuche? mit php oder Mysql ?
 
wenn du einen vernünftigen Index auf die Tabelle legst, ist das mit der Suche kein Problem. Da wird die Trennung mit ; sehr viel unperformanter.
Lange Tabellen sind auch nicht so dass Problem, eher Tabellen die sehr in die Breite gehen.

Bei deiner Benutzeranzahl mache ich mir da keine Sorgen, wenn es jedoch viel mehr werden könntest du dir Gedanken zu dem Benutzerverhalten machen. Wenn diese durchschnittlich jeden 2 Tag oder öfter vorbei schauen, könntest du auch nur die Daten speichern, an den der Benutzer nicht da war. Erhöht allerdings die Komplexität.

Alternativ könnte man Anweseheits- (oder Abwesenheits-) Intervalle speichern. Das macht es allerdings noch komplizierter.

Binäre Suche wirst du wahrscheinlich gar nicht brauchen, SQL liefert dir da genug Möglichkeiten. Aber vielleicht beschreibst du noch mal genauer was du mit diesen Daten überhaupt willst.
 
hmm also wenn es 100 Leute sind, die jeden Tage kommen, dann hättest Du also pro Jahr 100 * 365 Einträge in der Tabelle, also 36500-36600 Stück. Das mag viel klingen, aber mit den richtigen Indizes, langweilt das eine Datenbank. Selbst nach 10 Jahren mit 365000 Einträgen (+200-300 wegen den Schaltjahren) dürften Abfragen noch so flott gehen, dass Du keine Probleme bekommst. Wobei sich die Frage aufdrängt, wie lange die Daten überhaupt vorgehalten werden müssen. Wenn man z.B. jede Woche ein Skript laufen läßt, dass alle Einträge löscht, die älter als ein Jahr sind, dann hast du im Schnitt 37200-37300 Einträge in Deiner Tabelle (36500-36600 Jahresbestand + 700 für die seit der letzten Löschaktion aufgelaufenen Daten).

Im anderen Fall hättest Du pro Zeitstempel fürs Datum 6 bis 10 Zeichen (entweder 080509 oder 09.05.2008) und für die Uhrzeit 6 bis 8 Zeichen (110800 oder 11:08:00), dazu noch ein Trennzeichen zwischen Datum und Uhrzeit und eines für die Trennung zwischen zwei Zeitstempeln. Macht 20 Zeichen pro Login im Maximalausbau. Um die Daten eines Jahres speichern zu können musst Du also 7300 Byte zusammengepfercht in einer Tabelle ablegen und bei Bedarf da wieder rauskramen, und das pro User.
Neben der unbequemen und rechenintensiven Zugriffsart, kannst Du auch nicht mal schnell eben abfragen, wer denn alles am x.x.200x eingeloggt war.
Das Schlimme ist aber die Zugriffsart, weil Du immer Logik verwenden musst, um die Daten zu verarbeiten, während im ersten Fall ein einfacher SQL Befehl reicht. Diesen könntest Du bei Interesse z.B. auch einfach mal im phpMyAdmin absetzen und Dir so Auswertungen ausgeben lassen, wieviele Benutzer an den verschiedenen Tagen online waren und wo die Spitzen sind, ohne dass Du dafür jetzt extra ein Skript schreiben musst (wie in Fall zwei).
 
ok, danke fuer die Antworten... ist jetzt um einiges klarer...

eine frage noch, wie kann ich die keys verteilen? skooli hat in seinem ersten Beitrag vorgeschlagen, primary keys auf person und datum, aber ich dachte, dass ein primary key nur einmal vorkommen kann...

wie kann ich ueberpruefen ob ein index angelegt wurde ?
 
du kannst primary keys über mehrere Spalten legen (in diesem Fall sogar sinnvoll, da weder Datum noch User eindeutig ist und ein extra Spalte für den Schlüssel macht hier keinen Sinn).

Code:
ALTER TABLE `table1`
ADD PRIMARY KEY (`spalte1`, `spalte2`);

CREATE TABLE `table1`(
`spalte1` <rowtype> NOT NULL,
`spalte2` <rowtype> NOT NULL,
PRIMARY KEY (`spalte1`, `spalte2`));

<rowtype> entsprechend ersetzen, in deinem Fall wahrscheinlich int und date/datetime.
Über Primarey Keys liegt automatisch auch ein Index.
Wenn du jetzt noch wissen willst, welche Benutzer am Tag X anwesend waren (wenn du eine SQL-Anfrage dieser Art verwenden willst) dann solltest du dir noch nen Index übers Datum legen. Analog für die User.

Schau mal auf dir mal die ALTER/Create TABLE Syntax auf mysql.com an. Da steht wie das geht.

SHOW CREATE TABLE tablename liefert dir Infos über die Tabelle, alternativ auch die Struktur seite von PMA
 
Zurück
Oben