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 ...
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?
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:
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:
Und Spieler, die nie verlassen haben werden noch nicht berücksichtigt.
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:
Wir könnten auch die SQL player
OVERLAPS
übernimmt automatisch den früheren Wert des Paares als Anfang. Jeder Zeitraum gilt als halb offen intervalOVERLAPS
, außerstart <= time < end
undstart
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
:
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:
Tags und Links sql php postgresql overlap date-range