Finden überschneidende Zeiträume in PostgreSQL
Ist das richtig?
SELECT *
FROM contract
JOIN team USING (name_team)
JOIN player USING(name_player)
WHERE name_team = ?
AND DATE_PART('YEAR',date_join)>= ?
AND DATE_PART('YEAR',date_leave)<= ?
Meinem Tisch contract
hat den Spieler-Namen, team-Namen und die Termine, wenn er kam und verließ den club.
Ich will eine Funktion mit der Auflistung aller Spieler, die sich auf das team in bestimmten Jahren.
Die Abfrage scheint nicht zu funktionieren ...
- Kannst du die Fehler?
- es gibt keine Fehler.. die Ergebnisse sind nicht korrekt..
- Dann müssen Sie nicht die Daten für die Kriterien, die Sie angegeben haben
Du musst angemeldet sein, um einen Kommentar abzugeben.
Warum nicht zwischen ohne den date-Teil Sache:
oder sowas?
Den derzeit akzeptierte Antwort Antwort auf die Frage nicht. Und es ist prinzipiell falsch.
a BETWEEN x AND y
übersetzt:Einschließlich der oberen Grenze, während die Menschen müssen in der Regel ausschließen es:
Mit Termine können Sie leicht anpassen. Für das Jahr 2009 verwenden '2009-12-31' als Obere Grenze.
Aber es ist nicht so einfach mit Zeitstempel, die es erlauben Nachkommastellen. Moderne Postgres-Versionen verwenden Sie ein 8-byte-Ganzzahl intern zum speichern von bis zu 6 Bruch-Sekunden (µs Auflösung). Dieses wissen wir könnte noch machen, damit es funktioniert, aber das ist nicht intuitiv und richtet sich auf eine Implementierung detail. Schlechte Idee.
Darüber hinaus
a BETWEEN x AND y
findet nicht überlappende Bereiche. Wir brauchen:Und Spieler, die nie verlassen sind nicht als, noch.
Richtige Antwort
Vorausgesetzt, die Jahr
2009
, werde ich formuliere die Frage, ohne seine Bedeutung zu verändern:"Finden sich alle Spieler eines Teams, die sich vor 2010 nicht verlassen, bevor Sie 2009."
Basic-Abfrage:
Aber es gibt noch mehr:
Wenn die referenzielle Integrität erzwungen wird mit FK-constraints der Tabelle
team
selbst ist nur Lärm in die Abfrage und entfernt werden kann.Während die gleichen Spieler verlassen können und wieder das gleiche team, wir brauchen auch die Falte möglich, Duplikate, zum Beispiel mit
DISTINCT
.Und wir kann müssen für einen besonderen Fall: Spieler, die nie verlassen. Vorausgesetzt, die Spieler haben NULL in
date_leave
."Ein Spieler, der nicht bekannt ist, verlassen haben, wird davon ausgegangen, dass das spielen für die Mannschaft an diesem Tag."
Verfeinert Abfrage:
Operator-Rangfolge arbeitet gegen uns,
AND
bindet, bevorOR
. Wir brauchen Klammern.Ähnlichen Antwort mit optimierten
DISTINCT
(wenn Duplikate sind üblich):Normalerweise Namen von natürlichen Personen sind nicht einzigartig und ein Surrogat Primärschlüssel verwendet wird. Aber offensichtlich
name_player
ist der Primärschlüssel derplayer
. Wenn alles, was Sie brauchen, ist die Namen der Spieler, die wir nicht brauchen, die Tabelleplayer
in der Abfrage entweder:SQL
OVERLAPS
BetreiberDas Handbuch:
Kümmern potential
NULL
Werte,VERSCHMELZEN
scheint am einfachsten:Bereich Typ mit index-Unterstützung
In Postgres 9.2 oder höher Sie können auch arbeiten mit tatsächlichen range-Typen:
Range-Typen hinzufügen, die einigen Aufwand und mehr Platz einnehmen. 2 x
date
= 8 Byte; 1 xdaterange
= 14 Byte auf der Festplatte oder 17 bytes im RAM. Aber in Kombination mit der overlap-operator&&
die Abfrage kann unterstützt werden mit einem GiST index.Auch, keine Notwendigkeit zu speziellen-Fall NULL-Werte. NULL bedeutet "open range" in einem Bereich geben - genau das, was wir brauchen. Die definition der Tabelle selbst nicht verändern: wir können das Angebot geben Sie on-the-fly - und unterstützen Sie die Abfrage mit einem passenden Ausdruck-index:
Verwandte: