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?

War es hilfreich?

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.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top