Registrieren einzelne Zeilen aus einer Tabelle in MySQL
-
30-09-2019 - |
Frage
Ich habe zwei Tabellen players
und scores
.
Ich möchte etwas einen Bericht, sieht wie folgt generieren:
player first score points
foo 2010-05-20 19
bar 2010-04-15 29
baz 2010-02-04 13
Im Moment meine Abfrage sieht wie folgt aus:
select p.name player,
min(s.date) first_score,
s.points points
from players p
join scores s on s.player_id = p.id
group by p.name, s.points
Ich brauche die s.points
, die mit der Folge, dass min(s.date)
zurückkehrt zugeordnet ist. Geschieht, dass mit dieser Abfrage? Das heißt, wie kann ich sicher sein, ich bin den richtigen s.points
Wert für die verbundene Reihe zu bekommen?
Randbemerkung: Ich stelle mir das irgendwie zu MySQL Mangel an dicht Ranking zusammenhängt. Was ist die beste Abhilfe hier?
Lösung
Das ist das größte-n-pro-Gruppe Problem, das häufig auf Stack-Überlauf kommt.
Hier ist meine übliche Antwort:
select
p.name player,
s.date first_score,
s.points points
from players p
join scores s
on s.player_id = p.id
left outer join scores s2
on s2.player_id = p.id
and s2.date < s.date
where
s2.player_id is null
;
Mit anderen Worten gegeben Punktzahl s, versuchen, eine Punktzahl s2 für den gleichen Spieler zu finden, aber mit einem frühen Zeitpunkt. Wenn keine frühere Partitur gefunden wird, dann ist s die frühestens ein.
Re Ihre Kommentare über Beziehungen: Sie haben eine Politik haben, für die man im Falle eines Unentschiedens zu verwenden. Eine Möglichkeit ist es, wenn Sie mit automatischer Erhöhung verwenden Primärschlüssel, der mit dem geringsten Wert ist der frühere. Siehe den zusätzlichen Begriff in den äußeren Verknüpfung unter:
select
p.name player,
s.date first_score,
s.points points
from players p
join scores s
on s.player_id = p.id
left outer join scores s2
on s2.player_id = p.id
and (s2.date < s.date or s2.date = s.date and s2.id < s.id)
where
s2.player_id is null
;
Im Grunde müssen Sie tiebreaker Begriffe hinzuzufügen, bis Sie auf eine Säule herunterkommen, die zumindest für den gegebenen Spieler einzigartig sein, garantiert wird. Der Primärschlüssel der Tabelle ist oft die beste Lösung, aber ich habe Fälle gesehen, wo eine andere Säule geeignet war.
Im Hinblick auf die Kommentare, die ich mit @OMG Ponies geteilt, denken Sie daran, dass diese Art der Abfrage Vorteile enorm von der rechten Seite Index.
Andere Tipps
Die meisten RDMBS wird nicht einmal lassen Sie nicht aggregierten Spalten in der SELECT-Klausel enthalten, wenn GROUP BY verwenden. In MySQL, werden Sie sich mit Werten von Zufallsreihen für Ihre Nicht-Aggregat-Spalten beenden. Dies ist nützlich, wenn Sie tatsächlich den gleichen Wert in einer bestimmten Spalte für alle Zeilen haben. Daher ist es schön, dass MySQL uns nicht beschränken, obwohl es ist eine wichtige Sache zu verstehen.
Ein ganzes Kapitel ist dies gewidmet in SQL Antipatterns.