Ankündigung

Einklappen
Keine Ankündigung bisher.

vergleichen unbeschränkt vieler Zeitspannen auf Überschneidung

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • #16
    Hört sich plausibel an. Aber wenn ich so darüber nachdenken will, stehe ich schon vor dem ersten Problem: Wie berechne ich die Schnittmenge? Laut google (und meinen erinnerungen an die Schulzeit) ging das nur mit dem Element-Zeichen usw, aber das kann ich ja nicht in eine PHP-Datei einbauen...

    Kommentar


    • #17
      Nun Schnittmenge ist nur ein anderes Wort für das was du umgangssprachlich als Überschneidung bezeichnest. Es ist genau die Zeitspanne, deren Zeitpunkte alle in beiden der vorgegebenen Zeitspannen liegen.
      Bespiel:
      Zeitspanne1 von 2017-05-31 02:00 bis 2017-06-01 16:00
      Zeitspanne2 von 2017-05-31 17:00 bis 2017-06-01 22:00

      Die Schnittmenge ist dann die Zeitspanne von 2017-05-31 17:00 bis 2017-06-01 16:00.

      Für die Berechnung per PHP empfiehlt es sich auch wenn es nur wenige Zeilen sind allein wegen der besseren Testbarkeit dies als Funktion/Closure/Methode zu schreiben.

      Kommentar


      • #18
        Zitat von derwunner Beitrag anzeigen

        Erledigt ist was anderes. 64 Bit verschiebt das Problem nur.
        Die Erde ist geschätzt 4,5 Milliarden Jahre alt, die Milchstraße ca. 13,1 Milliarden Jahre, das Universum ~13,8 Milliarden Jahre

        Die "Verschiebung" wird reichen...
        Durch die 64-Bit-Umstellung kann der POSIX-Zeitstempel 292 Milliarden Jahre zuverlässig arbeiten, ohne dass es zu einem Überlauf kommt.
        https://de.wikipedia.org/wiki/Jahr-2038-Problem
        Über 90% aller Gewaltverbrechen passieren innerhalb von 24 Stunden nach dem Konsum von Brot.

        Kommentar


        • #19
          Nö, lstegelitz , so wie hier benutzt "nur" bis zum Jahr 9999. Denn 5-stellige Jahreszahlen verkraftet weder strtotime noch die DateTime.
          Danke dir dennoch für die Richtigstellung, ich selbst war zu faul das auszurechnen.

          Kommentar


          • #20
            Das wäre dann die Lösung nach ISO8601, Datum und Uhrzeit in der Notation YYYYMMDDhhiiss. Sollte ausreichen, das weder unsere noch die 25 Nachfolgegenerationen sich darüber groß den Kopf zerbrechen müssten.

            Über 90% aller Gewaltverbrechen passieren innerhalb von 24 Stunden nach dem Konsum von Brot.

            Kommentar


            • #21
              Zitat von JohnHSmith Beitrag anzeigen
              ich schreibe z.Zt. ein Plugin für Wordpress. Dort wird per Formular ein Datenbankeintrag mit einer Uhrzeit und Länge(in Stunden, INT) gesetzt. Jetzt möchte ich, dass angezeigt wird, sobald sich 4 dieser Zeiträume überschneiden.

              Ich dachte mir, ob es evtl sinnvoll wäre, ein Array daraus erstellen zu lassen, und diese dann zu vergleichen. Aber da würden sich ja alle miteinander vergleichen...
              Da es unbeschränkt viele sein sollen, würde ich SQL nehmen.
              Ich hoffe, ich hab Dich / die Diskussion verstanden. Hier ist ein Ansatz:
              http://rextester.com/FLAQKM33542

              Bruteforce Mengenlehre, kann man sicher noch optimieren, mit Index jedenfalls und wer weiß was noch.
              Nicht schön, aber funktioniert im Beispiel.


              Kommentar


              • #22
                jspit Okay, danke dir schon mal für den Ansatz. Bringt es mir etwas mit http://php.net/manual/de/dateinterval.format.php zu arbeiten?
                Perry Staltic Hm, die ausgabe in deinem Link ganz unten überschneidet sich doch nicht...? Oder hab ich einen Denkfehler?

                Kommentar


                • #23
                  Zitat von Perry Staltic Beitrag anzeigen
                  Da es unbeschränkt viele sein sollen, würde ich SQL nehmen.
                  Ich hoffe, ich hab Dich / die Diskussion verstanden. Hier ist ein Ansatz:


                  Bruteforce Mengenlehre, kann man sicher noch optimieren, mit Index jedenfalls und wer weiß was noch.
                  Nicht schön, aber funktioniert im Beispiel.

                  Nice brute force

                  Wenn Du aber bis 5 haben willst mußt das wieder anpassen, gell? Das dürfte recht schnell in sich explodieren vom Aufwand her. Vielleicht ist es besser, generell zu zählen, wie oft es sich überlappt, und dann darauf mit Where operieren. Ansatz mit PG, Datenrange und Index:

                  Code:
                  test=*# \d hotel2;
                       Tabelle »public.hotel2«
                   Spalte  |    Typ    | Attribute
                  ---------+-----------+-----------
                   id      | integer   | not null
                   von_bis | daterange |
                  Indexe:
                      "hotel2_pkey" PRIMARY KEY, btree (id)
                      "index_von_bis" gist (id, von_bis)
                  
                  test=*# select * from hotel2;
                   id |         von_bis         
                  ----+-------------------------
                    1 | empty
                    2 | [2017-01-01,2017-01-02)
                    3 | [2017-01-01,2017-01-03)
                    4 | [2017-01-03,2017-01-04)
                    5 | [2017-01-03,2017-01-05)
                    6 | [2017-01-07,2017-01-09)
                    7 | [2017-01-01,2017-01-09)
                  (7 Zeilen)
                  test=*# \d hotel2;
                       Tabelle »public.hotel2«
                   Spalte  |    Typ    | Attribute
                  ---------+-----------+-----------
                   id      | integer   | not null
                   von_bis | daterange |
                  Indexe:
                      "hotel2_pkey" PRIMARY KEY, btree (id)
                      "index_von_bis" gist (id, von_bis)
                  
                  test=*# select * from hotel2;
                   id |         von_bis         
                  ----+-------------------------
                    1 | empty
                    2 | [2017-01-01,2017-01-02)
                    3 | [2017-01-01,2017-01-03)
                    4 | [2017-01-03,2017-01-04)
                    5 | [2017-01-03,2017-01-05)
                    6 | [2017-01-07,2017-01-09)
                    7 | [2017-01-01,2017-01-09)
                  (7 Zeilen)
                  
                  test=*# select h1.id, sum(case when h1.von_bis && h2.von_bis then 1 else 0 end) as anzahl from hotel2 h1 cross join hotel2 h2 where h1.id != h2.id group by h1.id order by id;
                   id | anzahl
                  ----+--------
                    1 |      0
                    2 |      2
                    3 |      2
                    4 |      2
                    5 |      2
                    6 |      1
                    7 |      5
                  (7 Zeilen)
                  
                  test=*# explain analyse select h1.id, sum(case when h1.von_bis && h2.von_bis then 1 else 0 end) as anzahl from hotel2 h1 cross join hotel2 h2 where h1.id != h2.id group by h1.id order by id;
                                                                                   QUERY PLAN                                                                  
                  ---------------------------------------------------------------------------------------------------------------------------------------------
                   GroupAggregate  (cost=10.97..36397.31 rows=1270 width=68) (actual time=0.109..0.218 rows=7 loops=1)
                     Group Key: h1.id
                     ->  Nested Loop  (cost=10.97..24297.39 rows=1611630 width=68) (actual time=0.070..0.157 rows=42 loops=1)
                           Join Filter: (h1.id <> h2.id)
                           Rows Removed by Join Filter: 7
                           ->  Index Scan using hotel2_pkey on hotel2 h1  (cost=0.15..67.20 rows=1270 width=36) (actual time=0.020..0.050 rows=7 loops=1)
                           ->  Materialize  (cost=10.81..39.86 rows=1270 width=36) (actual time=0.006..0.008 rows=7 loops=7)
                                 ->  Bitmap Heap Scan on hotel2 h2  (cost=10.81..33.51 rows=1270 width=36) (actual time=0.036..0.042 rows=7 loops=1)
                                       Heap Blocks: exact=1
                                       ->  Bitmap Index Scan on index_von_bis  (cost=0.00..10.50 rows=1270 width=0) (actual time=0.006..0.006 rows=13 loops=1)
                   Planning time: 0.228 ms
                   Execution time: 0.296 ms
                  (12 Zeilen)
                  
                  test=*#
                  PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

                  Kommentar


                  • #24
                    Zitat von JohnHSmith Beitrag anzeigen
                    jspit Okay, danke dir schon mal für den Ansatz. Bringt es mir etwas mit http://php.net/manual/de/dateinterval.format.php zu arbeiten?
                    Nein, DateInterval sind ja nur Zeitdauer (Eine bestimmte Anzahl Sekunden, Minuten..) . Was du brauchst sind ja die konkreten Start und Endzeiten.
                    Fürs Verständnis spendier ich mal eine Funktion welche die Schnittmenge ermittelt:

                    PHP-Code:
                      /*
                       * return the intersect interval as array($start, $end)
                       * return false if interval empty
                       * param $start1 as DateTime ($start1 <= $end1)
                       * param $end1 as DateTime ($end1 >= $start1)
                       * param $start2 as DateTime ($start2 <= $end2)
                       * param $end2 as DateTime ($end2 >= $start2)
                       */
                      
                    function dateTimeSpanIntersect(DateTime $start1DateTime $end1DateTime $start2DateTime $end2)
                      {
                        if(
                    $end1 <= $start2 || $end2 <= $start1) return false;
                        
                    $start Max($start1,$start2);
                        
                    $end Min($end1,$end2);
                        return array(
                    $start$end);
                      } 
                    Ich habe jedoch Zweifel, ob jedesmal alle Datensätze untereinander abgeglichen werden müssen.
                    Um das zu beurteilen, fehlt das Hintergrundwissen. Geht es um so ein Thema wie Raumplanung und -belegung?
                    Wenn ja, dann reicht es womöglich die aktuelle Eingabe gegen die Datenbankeinträge abzugleichen?


                    Kommentar


                    • #25
                      Naja, es geht um 4 Räume, welche gemietet werden. Insofern können nur 4 gleichtzeitig buchen. Und ich möchte mir eben per AJAX anzeigen lassen, um welche Uhrzeiten es noch geht. Aber ich war der Meinung, dass es deutlich einfacher ist, ausgeben zu lassen, wann NICHT mehr gebucht werden kann.
                      Danke für den Code!

                      Kommentar


                      • #26
                        In dem Fall solltest Du in der DB passende Constraints definieren, die eine Überbuchung definitiv verhindern.
                        PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

                        Kommentar


                        • #27
                          Naja, mir geht es ja um die Ausgabe, die eingabe kann ich ja per PHP regeln.

                          Kommentar


                          • #28
                            Und warum ermittelst du nicht einfach für eine Formulareingabe welche dir letztendlich eine Start- und Endezeit liefert die freien Räume?
                            Auszuweisen für welche Zeiten noch gebucht werden kann ist dann noch ein anderes Thema.

                            Kommentar


                            • #29
                              Wir drehen uns im Kreis, denn diese unbeantworteten Fragen hatte ich in meinem Beitrag #5 schon gestellt.
                              Wären sie beantwortet worden, wären wir hier schon ein gutes Stück weiter.

                              Er speichert ja Startzeit und Dauer, müsste aber Startzeit und Endzeit lauten oder so wie akrechmer es dargestellt hat, wenn er denn Postgres nimmt.

                              Kommentar


                              • #30
                                Zitat von JohnHSmith Beitrag anzeigen
                                Naja, mir geht es ja um die Ausgabe, die eingabe kann ich ja per PHP regeln.
                                Sicher. Das ganze darf aber sicher auch alles in schnell funktionieren, oder? Mit steigender Anzahl von Datensätzen (siehe Betreff, Hint: 'unbeschränkt viele') wird eine DB-basierte Lösung (und zwar eine richtige, mit Constraints und vor allem nutzbaren Indexen) die einzig gangbare Lösung sein.
                                PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

                                Kommentar

                                Lädt...
                                X