knifflige Abfrage

copy68

Benutzer
Beiträge
7
Hallo,

ich habe eine Tabelle in der Eventdaten gespeichert werden. Dort wird das Startdatum , Enddatum (timestamps) sowie die Tage in Bitweiser Form (Ursprung Checboxen 1 Monatag, 2 Dienstag 4 Mittwoch usw.) gespeichert.

Nun möchte ich einen bestimmten Zeitraum auslesen Z.b ab dem 01.04.2013 bis zum 25.05. 2013 alle Daten die eine Montag haben also Feld tage &1. Da der Montag im Zeitraum natürlich öfter vorkommt muss ich das per PHP berechnen oder? Ich bekommen ja nur ein Ergebniss zurück. Im Moment gehe ich jeden Tag durch ab dem 01.04 bis zum 25.05.

Gibt es da eine andere Lösung, Im dem die Datensätze praktisch generiert werden? Also: finde alle Montage in Bereich und generiere mir ALLE Zeilen dazu, nicht nur eine weil sie im Bereich liegt.

Vg

copy
 
Werbung:

akretschmer

Datenbank-Guru
Beiträge
9.851
Hallo,

ich habe eine Tabelle in der Eventdaten gespeichert werden. Dort wird das Startdatum , Enddatum (timestamps) sowie die Tage in Bitweiser Form (Ursprung Checboxen 1 Monatag, 2 Dienstag 4 Mittwoch usw.) gespeichert.

Nun möchte ich einen bestimmten Zeitraum auslesen Z.b ab dem 01.04.2013 bis zum 25.05. 2013 alle Daten die eine Montag haben also Feld tage &1. Da der Montag im Zeitraum natürlich öfter vorkommt muss ich das per PHP berechnen oder? Ich bekommen ja nur ein Ergebniss zurück. Im Moment gehe ich jeden Tag durch ab dem 01.04 bis zum 25.05.

Gibt es da eine andere Lösung, Im dem die Datensätze praktisch generiert werden? Also: finde alle Montage in Bereich und generiere mir ALLE Zeilen dazu, nicht nur eine weil sie im Bereich liegt.

Vg

copy


Ich würde es so machen, ist aber PG:

Code:
test=*# create table copy68 (von date, bis date, tage int[]);
CREATE TABLE
test=*# insert into copy68 values ('2013-04-01','2013-05-25', array[1,2]);
INSERT 0 1
test=*#

Das array enthält 1 und 2 für Montag und Dienstag.

Abfrage:

Code:
test=*# select * from (select tage, generate_series(von::timestamp, bis::timestamp,'1day')::date as datum from copy68)foo where extract (dow from datum) = any(tage);
 tage  |   datum
-------+------------
 {1,2} | 2013-04-01
 {1,2} | 2013-04-02
 {1,2} | 2013-04-08
 {1,2} | 2013-04-09
 {1,2} | 2013-04-15
 {1,2} | 2013-04-16
 {1,2} | 2013-04-22
 {1,2} | 2013-04-23
 {1,2} | 2013-04-29
 {1,2} | 2013-04-30
 {1,2} | 2013-05-06
 {1,2} | 2013-05-07
 {1,2} | 2013-05-13
 {1,2} | 2013-05-14
 {1,2} | 2013-05-20
 {1,2} | 2013-05-21
(16 rows)

Andreas
 

ukulele

Datenbank-Guru
Beiträge
4.702
Ich hab das Problem irgendwie noch nicht ganz verstanden. Du hast einen Timestamp von und bis, also einen Zeitraum in deinem Datensatz. Du prüfst jetzt ob ein anderes Datum? / oder ein anderer Zeitraum? in diesem Zeitraum liegt oder sich mit diesem überschneidet?
 

akretschmer

Datenbank-Guru
Beiträge
9.851
Ich hab das Problem irgendwie noch nicht ganz verstanden. Du hast einen Timestamp von und bis, also einen Zeitraum in deinem Datensatz. Du prüfst jetzt ob ein anderes Datum? / oder ein anderer Zeitraum? in diesem Zeitraum liegt oder sich mit diesem überschneidet?

Wenn ich es richtig verstanden habe, dann sowas: ein Event (z.B. Kurs an einer Abendschule) geht von - bis immer Montags. nenne mir alle Termine.

Andreas
 

copy68

Benutzer
Beiträge
7
Hallo,

erstmal Danke für eure Antworten.

Genau wie akretschmer es sagt. Ich habe Events die mit einem Anfangsdatum und Endatum versehen sind. Allerdings kommen nur noch die Tage an denen der Event stattfindet hinzu. (Alles in einem Datensatz) Diese sind wie gesagt binär gespeichert. Also kann jeder Eintrag mehrmals vorkommen. Ich kann nicht einfach abfragen, hole mir alle Daten von bis und Montags. Dann kommt genau 1 Eintrag.

Im Moment gehe ich komplett alle Tage einzeln durch ab dem gegebenen Datum oder heute und schaue ob eine Datensatz vorliegt.

Also sinngemäss:

Select * form dates where dateform >=timestampheute and dateto <=timetstampheute and tage &1 (montag)

Bei nächsten Durchlauf erhöhe ich den timestampheute um 86400 (1Tag) sowie tag auf &2 , &4 usw. und das ganze geht von vorne los.

In der DB stehen allerdings sehr viele Events, so das es sehr zeitaufwändig ist. Ich begrenze die Anzahl zwar auf 10 Durchläufe, habe jetzt aber auch das Problem mit dem Paginator, da die Daten ja berechnet sind.

Ich hoffe diesmal ist es etwas verständlicher.

Vg
copy
 

akretschmer

Datenbank-Guru
Beiträge
9.851
Im Moment gehe ich komplett alle Tage einzeln durch ab dem gegebenen Datum oder heute und schaue ob eine Datensatz vorliegt.

Also sinngemäss:

Select * form dates where dateform >=timestampheute and dateto <=timetstampheute and tage &1 (montag)

Bei nächsten Durchlauf erhöhe ich den timestampheute um 86400 (1Tag) sowie tag auf &2 , &4 usw. und das ganze geht von vorne los.

Abfragen in Schleifen sind generell *zensiert*

Andreas
 

ukulele

Datenbank-Guru
Beiträge
4.702
Okay ich beginne zu verstehen :)

Also, nur um mich besser rein versetzen zu können, zu einem Event das vom 1.1. bis zum 31.1.2013 gehen würde und immer Dienstag und Mittwoch statt findet hättest du zwei Einträge.
Eintrag A) vom 01.01.2013 bis 29.01.2013 Tag Dienstag und
Eintrag B) vom 02.01.2013 bis 30.01.2013 Tag Mittwoch

Jetzt willst du beide Einträge anzeigen lassen wenn du nach Events aus Januar mit einem Montag suchst?
 

copy68

Benutzer
Beiträge
7
Hallo ukulele,

nicht ganz. ;) Ein Event vom 01.01.2013 bis um 29.01.2013 kann MEHRERE Tage beinhalten. Also das Event findet Montag und Donnerstags in diesem Zeitraum statt. Daher auch die Speicherung der Tage in binärform.

Im Datensatz kann z.b Tage = 66 gespeichert sein . Heisst: das Event findet am Dienstag und Donnerstag im genannten Zeitraum statt. Es ist aber ein Datensatz.

Row: datumvon: timestamp, datumbis: timstamp, tage: int wert, weitere Daten

Es sind praktisch wiederholende Termine an bestimmten Tagen.

Vg
copy
 

ukulele

Datenbank-Guru
Beiträge
4.702
Okay also immer nur ein Datensatz pro Event. Dann sollte das ganze doch recht einfach zu lösen sein. Du suchst nach allen Events die innerhalb eines Zeitraumsfallen oder sich mit diesem Überschneiden und an einem bestimmten Tag statt finden.
Code:
SELECT    *
FROM    tabelle
WHERE  (  datumvon BETWEEN @anfangszeit AND @endzeit
OR        datumbis BETWEEN @anfangszeit AND @endzeit )
AND        tag1 = 1
Wenn du für deinen Zeitraum Anfangs- und Endzeit angibst und guckst ob einer der beiden Timestamps der Events im Zeitraum liegt hast du eine Überschneidung, liegen beide im Zeitraum liegt das komplette Event in der gesuchten Zeit. Zusätzlich prüfst du noch den Tag ab.
 

copy68

Benutzer
Beiträge
7
Hallo ukulele,

fast so mach ich es. Nur ergibt sich das Problem das ich jeden Tag durchlaufen muss, da z.B der Montag in einem bestimmten Zeitraum ja öfter vorkommen kann. Also habe ich wieder die Abfrage ich eine Schleife. Ich benötige das für die Listenansicht der Events.

Montag 01.04. Event1

Monatg 01.04 Event 2

Mittwoch 03.04. Event 1

usw.


Zweitens habe ich das Problem mit dem Paging. Die Daten werden dann ja per PHP berechnet.Ich habe somit keinen "Bezugspunkt" also z.B Seite 3 fängt dann wo an? Das heisst ja ich müsste IMMER alle Datensätze durchgehen um eine bestimmte Seite aufzurufen.



vg

copy
 

ukulele

Datenbank-Guru
Beiträge
4.702
Nur ergibt sich das Problem das ich jeden Tag durchlaufen muss, da z.B der Montag in einem bestimmten Zeitraum ja öfter vorkommen kann. Also habe ich wieder die Abfrage ich eine Schleife. Ich benötige das für die Listenansicht der Events.
Warum ist für die Abfrage denn wichtig, das der Montag mehrfach vorkommen kann? Ich ging jetzt mal davon aus du hast einen Suchzeitraum x-y der sich mit den vorhandenen Events a-b, c-d usw. überschneidet oder nicht. Quasi zusätzlich suchst du nach Events die an einem Dienstag liegen, was ja in den vorhandenen Datensätzen per BIT vorgegeben ist. Das Event kommt also innerhalb des Zeitraums an jedem Dienstag vor weil ja nicht jeder Tag als eigenes BIT abgebildet ist. Wiso sollte ich jetzt alle Tage durchlaufen und was würde ich dann prüfen?

Montag 01.04. Event1

Monatg 01.04 Event 2

Mittwoch 03.04. Event
Da ja jedes Event nur einen Eintrag in der Tabelle hat gehe ich jetzt davon aus du möchtest diesen Eintrag einfach öfter ausgeben und zwar für jeden Tag an dem dein Event statt findet eine Zeile. Die Auswahl der Events passt also, nur die Ausgabe soll in mehreren Zeilen erfolgen - richtig?

Wenn dem so ist fällt mir vieleicht über Ostern was dazu ein :)

PS: Tut mir leid, normal bin ich nicht so schwer von Begriff. Versuche seit 3 Wochen eine Telefonnummer von Telekom zu Vodafone zu portieren, heute war der mein bisheriger nervlicher Tiefpunkt.
 

akretschmer

Datenbank-Guru
Beiträge
9.851
Da ja jedes Event nur einen Eintrag in der Tabelle hat gehe ich jetzt davon aus du möchtest diesen Eintrag einfach öfter ausgeben und zwar für jeden Tag an dem dein Event statt findet eine Zeile. Die Auswahl der Events passt also, nur die Ausgabe soll in mehreren Zeilen erfolgen - richtig?
So hatte ich es verstanden...

Wenn dem so ist fällt mir vieleicht über Ostern was dazu ein :)

Ich hab mal irgendwo eine MySQL-Version von generate_series() gesehen, der Rest kann dann faktisch bei mir abgeschrieben werden, das erlaub ich Dir ;-)

Andreas
 

copy68

Benutzer
Beiträge
7
Hallo ukulele,

genau das. Ein Event mehrere Zeilen.

Praktisch die Auflistung der Events. Entweder zu einem bestimmten Datum oder alle.
Im Moment gehe ich jeden Tag durch und schaue ob der Tag passt und packe den in ein Array, das später dann ausgegeben wird.

Danke an euch beide für die Hilfe.

Schöne Ostertage.

Vg

copy
 
Werbung:

copy68

Benutzer
Beiträge
7
Hallo,

ich wollte mich nur nochmal in Errinnerung rufen, da ich immer noch das Problem habe. Bin für jeden Tipp dankbar.

Vg

copy
 
Oben