Mailinglisten-Archive |
Hallo Hans, >nun, ich habe auch noch keine aufgebaut. Da ich hier im Allgäu >ein Infoportal aufsetzen will, muss ich mir überlegen wie die im Allgäu - ich dachte im Internet ;-) >- Branchendatenbank mit Zusatzinfos (256 Zeichen Suchbegriffe, > mehrere Brancheneinträge je Kunde...) > > und eben der > >- Veranstaltungskalender > >zu machen sind. Und Datenbank Design ist ja die Vorraussetzung für >eine gute schnelle Anwendung. Wohl wahr! > >Verschiedene andere Sachen habe ich schon entworfen aber grad beim >Veranstaltungskalender fällt mir keine so gute Lösung ein. Hmm, hab auchschon so einiges gemacht - also sollt einem doch hier auch was einfallen :-) >Der Haken ist ja, wie organisiert man Termine die wiederkehrend sind? >Einmal Termine ist ja leicht. Aber wie macht man das mit "Turnen jeden Dienstag" >oder noch dümmer, jeden ersten Donnerstag im Monat. :-| >Da habe ich noch nicht mal ne gute Idee. Denn das was Du mit 2 Tabellen beschrieben >hast, scheint mir etwas umständlich zu sein, zudem habe ich es nicht kapiert. Ok vielleicht versuch ich das nochmal zu erklären - ist zugegeben nicht so einfach und auch nicht die performanteste Lösung, aber ich glaub für gewisse Probleme mit Mysql ist es einfach auch die einzigste Lösung. Also folgendes Problem: In der Veranstaltungsdatenbank kann mit jedem Datensatz maximal ein Tag beschrieben werden, das heisst wenn jetzt eine Veranstaltung 5 Tage dauert, hat sie auch 5 Datensätze. Angenommen diese Veranstaltung findet aber jetzt mehrmals im Jahr statt - sozusagen in mehreren Blöcken. Selecten will ich nun immer nur den Anfang und das Ende jedes Blockes - so dass ich als output dann: row1 veranstaltung start row2 veranstaltung ende //Block 1 row3 veranstaltung start row4 veranstaltung ende //Block2 erhalte. Ich muss also irgendwie eine Bedingung in den Query packen dass ich nur die Rows will, auf die eine weitere Row folgt, von der selben Veranstaltung - nur eben der nächste Tag. D.h. die erste Row ist der Anfang einer Veranstaltung. Und ich will die Rows, zu denen es eine "Vorgänger" row gibt, aber keinen "Nachfolger" - das ist dann das Ende eines Blockes. Da ist dann auchschon das Problem: Row übergreifende Bedingung. hmm.. noch ein Bildchen dann ists einfacher: <datenbank inhalt> Datum1 Veranstaltung1 <--- Start des Blockes // Soll selected werden Datum1+1Tag Veranstaltung1 Datum1+2Tage Veranstaltung1 <--- Ende des Blockes // Soll selected werden <-- ... einige Zeit dazwischen ---> Datum2 Veranstaltung1 <--- Start des Blockes // Soll selected werden Datum2+1Tag Veranstaltung1 Datum2+2Tage Veranstaltung1 <--- Ende des Blockes // Soll selected werden </datenbank inhalt> (ich setzte ein ORDER BY datum voraus) Gut - jetzt kommt der Trick. wenn ich nur eine Tabelle hab hab ich ja in der Where-clause keine informationen darüber was z.b. in dem folgendem Datensatz drinsteht - das müsste ich aber wissen, um sagen zu können ob dieser Datensatz jetzt der letzte Tag einer Veranstaltung ist oder ob der folgende Datensatz wieder von dieser Veranstaltung ist und die Veranstaltung also noch weiter geht. ok? gut - trick also. Ich hab nur eine Tabelle - also mach ich in meinem Select 2 draus - Mysql kann das - ist zwar nicht so schnell weil (weis jetzt nicht genau wie mysql das handhabt) ich ja die Tabelle praktisch temporär einmal kopiere. Gut das macht man also so: "SELECT a.* FROM veranstaltungen a LEFT JOIN veranstaltungen b" Ich habe die Tabelle "veranstaltungen " und geb ihr 2 alias, nämlich a und b -> 2 Tabellen a,b mit selben Inhalt jetzt noch die Join Bedingung, also z.b. die Veranstaltungsnummer, die immer gleich ist. "SELECT a.* FROM veranstaltungen a LEFT JOIN veranstaltungen b ON vanummer" d.h. alle Datensätze in a werden mit denen aus b verschmolzen die die selbe vanummer haben - naja, das bringt nochnicht soviel - schliesslich will ich ja wissen ob ein gewisser Datensatz einen "Vorgänger" oder "Nachfolger" hat. also: "SELECT a.* FROM veranstaltungen a LEFT JOIN veranstaltungen b ON vanummer WHERE a.datum = SUBDATE(b.datum, INTERVAL 1 DAY) OR a.datum = ADDDATE(b.datum, INTERVAL 1 DAY)" Das gibt dann alle Veranstaltungsblöcke aus - so far noch nichts besonderes, und tierisch umständlich.. weiter aber: "SELECT a.* FROM veranstaltungen a LEFT JOIN veranstaltungen b ON vanummer WHERE (a.datum = SUBDATE(b.datum, INTERVAL 1 DAY) AND a.datum != ADDDATE(b.datum, INTERVAL 1 DAY)) OR (a.datum = ADDDATE(b.datum, INTERVAL 1 DAY) AND a.datum != SUBDATE(b.datum, INTERVAL 1 DAY)" Das müssts sein, ich habs zwar nich ausprobiert, aber ich denke es müsste gehen. Wie gesagt sollte man noch ein "ORDER BY datum" verwenden und falls man nur nach einer Veranstaltung sucht - noch ein "AND Where a.vanummer = 1234567" Ich bekomme also alle Rows die einen Nachfolger, aber keinen Vorgänger haben (Start) und alle Rows die einen Vorgänger, aber keinen Nachfolger haben. (Ende) Kann sein dass sich die Where-clause durch etwas Logik vereinfachen lässt, aber das muss jetzt nicht sein. Uff, soweit zum Tobi Problem. (Tobi, probiers bitte mal aus, würd mich interessieren obs geht - bzw. bin mir recht sicher das es gehen muss - aber ob der query so schon stimmt..) >Es kommt ja auch noch drauf an wie man das abfragen will. Was man mindestens >machen muss ist ja die tägliche Abfragemöglichkeit oder was ist innerhalb >eines definierten Zeitraumes an Terminen da. Das ist alles noch recht einfach, >aber wie sollte man das mit dem Stammtisch der jeden ersten Donnerstag stattfindet >in den Griff bekommen. Denn der Kunde soll ja eingeben können, "Stammtisch" ist >von April bis Oktober an jedem ersten Donnerstag im Monat. > >Und für die Aufgabe habe ich noch keine praktikalbel Idee. Hmm.. mir ist da grade ein Vorbild eingefallen - Falls Du Dich unter UNIX auskennst, da gibts ja jemanden der sich CRON nennt :-) (also der Daemon der periodische Prozesse ausführt - z.b. jede Nacht um 12 ein backup fahren oder sowas..) CRON hat eigentlich ein recht leistungsfähiges System um seine Termine zu koordinieren. Er verwendet folgendes format: 5 Werte, durch Lerzeichen getrennt - Minute (0-59) - Stunde (0-23) - Tag des Monats (1-31) - Monat im Jahr (1-12) - Tag der Woche (0-6) // 0=Sonntag, 6=Samstag Zitat UNIX, Markt&Technik, 93': "Mehrere Zeitangaben können durch Kommata getrrennt angegeben werden. Zeitbereiche können durch einen Bindestrich "-" angegeben werden. Das Zeichen "*" bedeutet dass alle erlaubten Werte verwendet werden." Damit würde "Montags, 16h turnen, von Februar bis August" so aussehen: 0 16 * 2-8 1 Damit lässt sich wirklich jeder Termin ausdrücken, ob über mehrere Tage, wöchentlich, monatlich oder was auch immer. (*grübel* nur jährlich nicht, aber das liesse sich ja implementieren) Hmm - soweit ein funkitonierendes System - jetzt muss man das nurnoch so umbauen, dass es elegant in einer Datenbank abgelegt werden kann - und da muss ich erstmal ein bisschen grübeln.. Zum grübeln bin ich jetzt kurz aufs Klo gegangen, da fällt einem sowas immer ein - also gerade tönte durch ganz Passau der aufschrei "ich habs! verdammt spinn ich oder was!" folgendes: (ist mir wirklich grad am klo eingefallen, kein witz) eine Woche hat 7 Tage, ein Monat 31, ein Tag 24 Stunden, eine Stunde 60 Minuten. toll, gell ;-) gut, trick: 7 Tage - ein Byte hat 8 Bit 31 Tage - 4 Byte haben 32 Bit 24 Stunden - 3 Byte haben 24 Bit 60 Minuten - 8 Byte haben 64 Bit den Ausdruck "-" von cron vergessen wir, den brauchen wir nicht. Ich mache es so: 5 Felder in der Datenbank um die Zeit zu codieren: - minute BIGINT (8Bytes, 64Bit) - hour MEDIUMINT (3Bytes, 24Bit) - dayofmonth INT (4Bytes, 32Bit) - month SMALLINT (2Bytes, 16Bit) - dayofweek TINYINT (1Byte, 8Bit) oops, alle UNSIGNED nicht vergessen. Wir verwenden einfach die Bitcodierung um die Werte auszudrücken. z.b. Januar ->1tes bit im month Feld ist 1 16:50 Uhr -> 16tes bit in hour ist 1, 50tes Bit in minute ist 1. nochmal das Beispiel mit dem Turnen, Montags 16h von Januar bis August - minute = 0 - hour = 16tes Bit gesetzt, sonnst alles 0 also das wäre der Wert 256 dezimal - dayofmonth = 0 - month = 1-8tes Bit ist 1, der Rest 0 -> Wert 65280 dezimal - dayofweek = 1tes Bit ist 1, der Rest 0 -> Wert 128 Was hältst Du davon? wenn man direkt auf der Datenbank arbeitet ist das zwar etwas unverständlich. aber mysql hat ja die demensprechenden Bit Funktionen um die Werte zu bearbeiten und auszudrücken. Ich sehe hier ne Menge Vorteile: - jeder Termin braucht nur eine Zeile - Speicheraufwand ist recht gering, Feldergrössen sind konstant - Speicheraufwand für beliebigen Termin sind 21Byte - das ist weniger als 2 Timestamp14 Felder - Komfortabel um Termine auszuwerten - z.b. "select * from termine where dayofweek = 128" // alle Termine die an Montagen stattfinden "select * from termine where month & 16 > 0" // alle Termine die im Mai stattfinden "select * from termine where month & 255 > 0" // alle Termine die zwischen Januar und August stattfinden Vielleicht sollte man bei den Minuten von einer Bitcodierung absehen, schliesslich hat man ja selten Termine die z.b. alle 5 minuten Stattfinden - naja, wie mans braucht - man spart damit 2 Byte :-) Um die Werte zu erzeugen Setzt man sich am besten Konstanten und verwendet Bitmasken, also z.b. $JANUAR = 1; $FEBRUAR = 2; $MÄRZ = 4; $APRIL = 8; $MAI = 16; $JUNI = 32; $JULI = 64; .... und dann einfach $wert = $JANUAR & $MÄRZ & $APRIL; "select * from termine where month & '$wert' > 0" // termine die im Januar und März und April stattfinden $wert = $JANUAR | $FEBRUAR "select * from termine where month & '$wert' > 0" // termine die im Januar oder Februar stattfinden Nachteil ist halt echt nur das Bit-gefiesel, aber mit Konstanten wirds easy und sehr angenehm zu lesen. Aber mal ehrlich - ich find das genial! hmm - das wär ja glatt ein Thema für nen Artikel auf PHP-Center.de , meinst Du nicht auch? Thema ist hiermit für einen Artikel reserviert :-) Verdammt hab ich jetzt nen Roman geschrieben - naja - Spass hats gemacht! Doch halt - fällt mir grade noch ein Manko ein: Wie codiere ich die Dauer der Veranstaltung minutengenau? z.b. Turnen täglich von 16:15 bis 18:35 *grübel* naja, vielleicht noch 2 felder dazu .hmm.. leider muss ich grad nicht aus klo ;-) also sowas wie Turnen von 16-18 Uhr geht schon.. aber die anfangs und end-Minuten kann ich nicht ausdrücken. hmm.. vielleicht irgendeine bit-komplementdarstellung - dann wirds übel, dann hab ich noch ein Vorzeichenbit - naja, am Klo dann.. bzw. in meinem Artikel ;-)) >Du siehst, alles nicht so einfach. na wie man sieht - auch hier nicht so einfach :-) >Was machst Du denn in Passau, wohnst Du da oder studierst Du dort? (Wahlbayer? ;) Ja, am Politischen Aschermittwoch lass ich hier meine Parolen hören ;-) schmäh ohne - ich Studier hier Informatik, 1tes Semester. >Liebe Grüße aus dem Allgäu Greetings auch wieder aus Passau >Hans Theo Mislisch martin
php::bar PHP Wiki - Listenarchive