Finde überlappende Datumsbereiche in PostgreSQL

8

Stimmt das?

%Vor%

Meine Tabelle contract hat den Spielernamen, den Teamnamen und die Daten, wann er beigetreten ist und den Verein verlassen hat.
Ich möchte eine Funktion erstellen, die alle Spieler auflistet, die in bestimmten Jahren im Team waren.
Die obige Abfrage scheint nicht zu funktionieren ...

    
aocferreira 18.12.2010, 23:22
quelle

2 Antworten

6

Warum nicht zwischen ohne das Datum Teil Ding verwenden:

WHERE datefield BETWEEN '2009-10-10 00:00:00' AND '2009-10-11 00:00:00'

oder so?

    
Scott Marlowe 19.12.2010, 05:33
quelle
48

Akzeptierte Antwort ist nicht gut

Die Antwort, die a BETWEEN x AND y vorschlägt, hat viele Upvotes bekommen und ist seit fast 2 Jahren akzeptiert. Aber es beantwortet nicht nur die Frage, es ist im Prinzip auch falsch .

a BETWEEN x AND y bedeutet:

%Vor%

Beinhaltet den oberen Rahmen, während Personen normalerweise ausschließen müssen:

%Vor%

Mit Daten können Sie leicht anpassen. Für das Jahr 2009 verwenden Sie '2009-12-31' als obere Grenze.
Aber es ist nicht so einfach mit Zeitstempeln , die Nachkommastellen erlauben. Moderne Postgres-Versionen verwenden intern eine 8-Byte-Ganzzahl, um bis zu 6 Sekundenbruchteile (μs Auflösung) zu speichern. Wenn wir wissen, dass wir können , funktioniert es immer noch, aber das ist nicht intuitiv und hängt von einem Implementierungsdetail ab. Schlechte Idee.

Darüber hinaus ist a BETWEEN x AND y in diesem speziellen Fall nutzlos, um Bereiche zu finden, die sich mit einem anderen Bereich überschneiden. Was wir brauchen, ist:

%Vor%

Und Spieler, die nie verlassen haben werden noch nicht berücksichtigt.

Richtige Antwort

Unter der Annahme des Jahres 2009 werde ich die Frage umformulieren, ohne ihre Bedeutung zu ändern:

"Finde alle Spieler eines bestimmten Teams, die vor 2010 beigetreten sind und nicht vor 2009 gegangen sind."

%Vor%

Operator Vorrang funktioniert gegen uns, AND bindet vor OR . Wir brauchen Klammern.

Wenn die referenzielle Integrität nicht unterbrochen wird, ist die Tabelle team selbst nur ein Geräusch in dieser Abfrage und kann entfernt werden.

Während ein und derselbe Spieler das gleiche Team verlassen kann, müssen wir auch mögliche Duplikate falten, zum Beispiel mit DISTINCT .

Und wir dürfen für einen besonderen Fall sorgen: Spieler, die nie gegangen sind. Angenommen, diese Spieler haben date_leave IS NULL .

"Ein Spieler, von dem nicht bekannt ist, dass er gegangen ist, wird bis zum heutigen Tag für das Team gespielt."

Bei dieser optimierten Abfrage angekommen:

%Vor%

Verwandte Antwort mit optimiertem% ​​co_de% (wenn Duplikate üblich sind):

In der Regel sind Namen nicht eindeutig und ein Ersatz-Primärschlüssel wird für natürliche Personen verwendet. Aber offensichtlich ist DISTINCT der Primärschlüssel von name_player . Wenn Sie nur Spielernamen benötigen, brauchen wir nicht die Tabelle player in der Abfrage, entweder:

%Vor%

Wir könnten auch die SQL player operator :

  

OVERLAPS übernimmt automatisch den früheren Wert des Paares als   Anfang. Jeder Zeitraum gilt als halb offen   interval OVERLAPS , außer start <= time < end und start sind gleich in denen   Fall es stellt diesen einzelnen Augenblick dar.

Aber wir müssen uns um mögliche end -Werte kümmern. Am einfachsten mit NULL :

%Vor%

In Postgres 9.2 oder höher können Sie auch mit arbeiten Bereichstypen in Kombination mit dem Überlappungsoperator COALESCE , die mit einem GiST-Index unterstützt werden können. Beispiel:

Erwin Brandstetter 08.03.2013 23:48
quelle