SQL: Nächstgelegenes Datum aus einer Gruppe ermitteln

Saugkraft

Aktives Mitglied
Thread Starter
Dabei seit
20.02.2005
Beiträge
9.022
Reaktionspunkte
3.189
Moin SQL Gurus,

ich brauche mal einen guten Tipp, wie ich aus einer Reihe von gruppierten Daten das nächstgelegene Datum ermitteln kann.

Angenommen, ich habe folgende Daten (Irgendwelche Events finden periodenweise statt):

Zeitraum 1:
1.7.2014
6.7.2014
9.7.2014

Zeitraum 2:
1.10.2014
6.10.2014
10.10.2014

Zeitraum 3:
1.11.2014
5.11.2014
11.11.2014

Heute ist der 9.10.2014.

Ich muss sicher ermitteln können, in welchem Zeitraum ich mich befinde. Weil heute der 9.10. ist, liege ich noch im Zeitraum 2. Der soll also angezeigt werden. Ab dem 11.10. (ggf. mit ein paar Tagen "Aufschlag") soll dann Zeitraum 3 angezeigt werden.

Die db Struktur sieht dazu so aus:
id (ID-Feld), zeitraum_id (in dem Fall 1-3, ist ein Fremdschlüssel), datum

Hat jemand eine Idee, wie ich das per SQL realisieren kann?

Schonmal danke. :)
 
Was steht denn in der Tabelle mit dem zeitraum Primärschlüssel? Stehen dort die Anfangs- und Enddaten der Zeiträume?
 
Hallo Saugkraft,

Du brauchst also deine Zeitraum ID?

Warum hast du denn 3 Daten in deinen Zeiträumen? Es reicht doch eigentlich Anfang und Ende?

So spontan hätte ich gesagt, das könnte ungefähr so gehen:

SELECT
Zeitraum_ID
FROM
Zeitraum_Table
WHERE
datenow >= Zeitraum_Begin
AND
datenow <= Zeitraum_Ende
;

datenow ist das Datum welches du benutzen willst, für Jetzt hilft da now() oder getdate().

Im nächsten Schritt kannst du die zurückgewonnene ID in dein INSERT Statement für dein Event benutzen.

Ich hoffe das hilft schonmal weiter! :D
 
Code:
SELECT MIN(zeitraum_id)
  FROM tabelle
 WHERE '2014-10-09' <= datum
;

Wie dann der "Aufschlag" angegeben wird, ist vom SQL Dialekt abhängig, in sqlite z.B.

Code:
SELECT MIN(zeitraum_id)
  FROM tabelle
 WHERE julianday('2014-10-11') <= julianday(datum) + 1
;
 
Was steht denn in der Tabelle mit dem zeitraum Primärschlüssel? Stehen dort die Anfangs- und Enddaten der Zeiträume?
Nee. Leider nicht. Ich muss mit den Daten arbeiten.

Warum hast du denn 3 Daten in deinen Zeiträumen? Es reicht doch eigentlich Anfang und Ende?
Weil ich die Datenbank nicht entworfen hab. :D Es wäre aber auch kontraproduktiv. Die Berechnung soll automatisch erfolgen.

Die 3 Daten sind im Prinzip zusammengehörige Einzeltermine. Zum Beispiel ein Kochkurs. Du buchst das Gesamtpaket, dein Kochlehrer trägt seinerseits die Termine ein, du bekommst die Daten in deiner Übersicht angezeigt.

Zeitraum 1: Sushi
Zeitraum 2: Kochen wie Mutti
Zeitraum 3: Italienisch Kochen

Heraus kommen soll eine Oberfläche, auf der ab Mitte/Ende Juli sinngemäß angezeigt wird: "Kochen wie Mutti. Hier klicken." Das dann natürlich bis zum 10.10. Danach dann irgendwann "Italienisch Kochen".

Theoretisch (und auch nur theoretisch) könnte ich die Datenbank natürlich erweitern. Faktisch aber nicht. "Zeitraum" hab ich nur geschrieben, um zu verdeutlichen, worum es geht. Tatsächlich wirst du datenbanktechnisch nämlich in die "Klasse" Sushi und die Klasse "Kochen wie Mutti" gesteckt. Da werden auch IDs vergeben, die sind aber wiederum auch nur Teil einer m:n Beziehung.

Die Zeiträume können sich theoretisch auch überschneiden. Dann wird heute Kochen wie Mutti, morgen Italienisch und übermorgen wieder Kochen wie Muttig angezeigt. Sofern es eben nicht über eine "Zeitraumtabelle" läuft, sondern aus den Einzelterminen ermittelt wird.

Jetzt könntest du fragen: Warum nicht einfach immer den nächsten Termin nehmen? Weil du zwischen Kochen wie Mutti (Kurs ist rum) und Italienisch Kochen (Kurs fängt nächsten Monat an) noch einen gewissen Zeitraum zur "Nachbearbeitung" haben sollst.
 
Code:
SELECT MIN(zeitraum_id)
  FROM tabelle
 WHERE '2014-10-09' <= datum
;

Danke. Aber was mache ich wenn die zeitraum_ids nicht in entsprechender Reihenfolge sind?

Zum Beispiel: 3946, 5543, 3329, 894

Ich könnte theoretisch auch mit top(1) .. where <= datum order by date group by zeitraum_id arbeiten.

Das ist mir aber alles zu festgelegt auf eine bestimmte Datenabfolge. Ich habe keine Ahnung wie die Daten in der DB stehen. Fehler muss ich logisch ausschließen und Fehleingaben (deshalb auch keine Eingabe des Zeitraums) so weit wie möglich abfangen.

Wie gesagt.. ich kann mit "PHP" (ich nutze ASP, ist aber wurscht) nacharbeiten wenn es keine reine SQL Lösung gibt.

Da fällt mir aber nur ein, die zeitraum_ids zu gruppieren, dann das jeweils erste oder letzte Datum auszuwählen und dann zu vergleichen. Dann brauche ich aber zwei SQL Abfragen für einen Zeitraum. top(1) datum asc und top(1) datum desc. Und dann kann ich erst vergleichen.

Das kriege ich im Spaghettistil programmiert. So ist das nicht. Ich kann das Zeug auch stumpf in ein Array oder eine XML Datei packen und dann ein eigenes Skript für die Ermittlung programmieren.. Zur Not gehe ich mit einer Schleife zig mal drüber und schreibe in verschiedene Variablen. Da geht einiges. :D

Ich hätte es aber gerne so schlank wie möglich. :teeth:
 
Wenn die Zeiträume sich nicht überschneiden, sollte das funktionieren
Code:
SELECT zeitraum_id
  FROM (
        SELECT MIN(datum) AS min_d
             , MAX(datum) AS max_d
             , zeitraum_id
          FROM tabelle
         GROUP BY zeitraum_id
        ) AS T
 WHERE '2014-10-09' BETWEEN T.min_d AND T.max_d
;
 
Grandios, danke. :)

Ich übersetze das mal in MS-SQL und probiere es aus. MS-SQL ist bei verschachtelten Abfragen ein bisschen zickig. Oder ich bin noch nicht gut genug. :D
 
Zurück
Oben Unten