MySQL: Holen Sie sich den neuesten Datensatz

80

In der unten stehenden Tabelle, wie bekomme ich nur die jüngste Aufzeichnung von id=1auf der Grundlage der signin Spalte und nicht alle drei Datensätze?

+----+---------------------+---------+
| id | signin              | signout |
+----+---------------------+---------+
|  1 | 2011-12-12 09:27:24 | NULL    |
|  1 | 2011-12-13 09:27:31 | NULL    |
|  1 | 2011-12-14 09:27:34 | NULL    |
|  2 | 2011-12-14 09:28:21 | NULL    |
+----+---------------------+---------+
Enchance
quelle

Antworten:

88

Verwenden Sie das MAX(signin)nach ID gruppierte Aggregat . Dies listet jeweils die aktuellsten signinauf id.

SELECT 
 id, 
 MAX(signin) AS most_recent_signin
FROM tbl
GROUP BY id

Um den gesamten einzelnen Datensatz INNER JOINabzurufen , führen Sie eine Abfrage gegen eine Unterabfrage durch, die nur die MAX(signin)pro ID zurückgibt .

SELECT 
  tbl.id,
  signin,
  signout
FROM tbl
  INNER JOIN (
    SELECT id, MAX(signin) AS maxsign FROM tbl GROUP BY id
  ) ms ON tbl.id = ms.id AND signin = maxsign
WHERE tbl.id=1
Michael Berkowski
quelle
Hier ist, was basierend auf Ihrer ersten Antwort SELECT id, MAX(signin) FROM tbl GROUP BY id WHERE id=1;
funktioniert hat
Ich habe versucht, die 2. Lösung (um die ganze Zeile zu erhalten) in meiner eigenen Situation zu implementieren, aber ich bekomme immer eine leere Ergebnismenge
rantsh
@rantsh xQberts Antwort hatte die richtige Version von dem, was ich ursprünglich oben hatte, aber ich bevorzuge die Lösung, die ich gerade geändert habe.
Michael Berkowski
@ MichaelBerkowski du meintest du bevorzugst meine Lösung? Es würde mir nichts ausmachen, eine positive Bewertung meiner Antwort zu erhalten, wenn dies der Fall ist
rantsh
1
@rantsh Ah, ich hatte nicht bemerkt, dass Sie etwas Ähnliches zu dem hinzugefügt haben, was ich gerade geändert habe, außer über USINGanstelle eines expliziten ON. Du hast eine +1 :)
Michael Berkowski
81
SELECT *
FROM   tbl
WHERE  id = 1
ORDER  BY signin DESC
LIMIT  1;

Der offensichtliche Index wäre auf (id), oder ein mehrspaltigen Index auf (id, signin DESC).

Praktischerweise sortiert MySQL die NULLWerte zuletzt in absteigender Reihenfolge. Das ist es, was Sie normalerweise wollen, wenn es NULLWerte geben kann : die Zeile mit der neuesten Nicht-Null signin.

So erhalten Sie NULLzuerst Werte:

ORDER BY signin IS NOT NULL, signin DESC

Verbunden:

Der SQL-Standard definiert nicht explizit eine Standardsortierreihenfolge für NULLWerte. Das Verhalten ist in verschiedenen RDBMS sehr unterschiedlich. Sehen:

Es gibt jedoch die NULLS FIRST/ NULLS LASTKlauseln, die im SQL-Standard definiert sind und von den meisten wichtigen RDBMS unterstützt werden, jedoch nicht von MySQL. Sehen:

Erwin Brandstetter
quelle
5
Das fühlt sich am saubersten an!
Karancan
Erwägen Sie, einen Index für die Anmeldespalte zu erstellen, um den Prozess erheblich zu beschleunigen
Alexei Tenitski
Verwenden SELECT TOP 1 *und entfernen Sie die LIMIT 1letzte Zeile. bei Verwendung von SQL Server. Verwenden Sie die oben genannten, wenn MySQL oder Postgres.
Jaredbaszler
Am saubersten. . . . . . . .
Stigzler
Einfach und sauber!
Jeremy Swagger
9

Aufbauend auf den Antworten von @ xQbert können Sie die Unterabfrage vermeiden UND generisch genug gestalten, um nach einer beliebigen ID zu filtern

SELECT id, signin, signout
FROM dTable
INNER JOIN(
  SELECT id, MAX(signin) AS signin
  FROM dTable
  GROUP BY id
) AS t1 USING(id, signin)
rantsh
quelle
Hallo, wie funktioniert diese Abfrage und ist sie effizienter als die Antwort von xQbert? Beide Abfragen werden für mich ungefähr zur gleichen Zeit ausgeführt, und ich verstehe nicht, dass der Verwendungsteil der Abfrage das ersetzt, was normalerweise und aktiv ist.
ZJS
3
Select [insert your fields here]
from tablename 
where signin = (select max(signin) from tablename where ID = 1)
xQbert
quelle
1
SELECT * FROM (SELECT * FROM tb1 ORDER BY signin DESC) GROUP BY id;
user3044573
quelle
1

Ich hatte ein ähnliches Problem. Mit anderen Worten, ich musste die letzte Version der Seiteninhaltsübersetzung abrufen, um den spezifischen Datensatz mit der höchsten Nummer in der Versionsspalte zu erhalten. Also wähle ich alle nach Version geordneten Datensätze aus und nehme dann die erste Zeile aus dem Ergebnis (unter Verwendung der LIMIT-Klausel).

SELECT *
FROM `page_contents_translations`
ORDER BY version DESC
LIMIT 1
Ales
quelle
1

Einfacher Weg zu erreichen

Ich weiß, es ist eine alte Frage. Sie können auch so etwas tun

SELECT * FROM Table WHERE id=1 ORDER BY signin DESC

Wenn Sie oben abfragen, ist der erste Datensatz der neueste Datensatz.

Für nur einen Datensatz können Sie so etwas wie verwenden

SELECT top(1) * FROM Table WHERE id=1 ORDER BY signin DESC

Die obige Abfrage gibt nur einen letzten Datensatz zurück.

Prost!

Ajmal Jamil
quelle