Ich habe folgende Tabelle:
id time text otheridentifier
-------------------------------------------
1 6 Apple 4
2 7 orange 4
3 8 banana 3
4 9 pear 3
5 10 grape 2
Ich möchte die 3 letzten Datensätze (nach Zeitabnahme) auswählen, deren otheridentifier
s verschieden sind. In diesem Fall wäre das Ergebnis also id
s: 5, 4 und 2.
id
= 3 wird übersprungen, da es einen neueren Datensatz mit demselben otheridentifier
-Feld gibt.
Folgendes habe ich versucht:
SELECT * FROM `table` GROUP BY (`otheridentifier`) ORDER BY `time` DESC LIMIT 3
Am Ende bekomme ich jedoch Zeilen mit id
= 5, 3 und 1 anstelle von 5, 4, 2 wie erwartet.
Kann mir jemand sagen, warum diese Abfrage nicht das zurückgibt, was ich erwartet habe? Ich habe versucht, ORDER BY in ASC zu ändern, aber dies ordnet die zurückgegebenen Zeilen einfach in 1, 3, 5 um.
Es gibt nicht das zurück, was Sie erwarten, da die Gruppierung vor der Anordnung erfolgt, wie durch die Position der Klauseln in der SQL-Anweisung angegeben. Sie werden leider schicker werden müssen, um die gewünschten Reihen zu erhalten. Versuche dies:
SELECT *
FROM `table`
WHERE `id` = (
SELECT `id`
FROM `table` as `alt`
WHERE `alt`.`otheridentifier` = `table`.`otheridentifier`
ORDER BY `time` DESC
LIMIT 1
)
ORDER BY `time` DESC
LIMIT 3
Sie können die Tabelle in sich zusammenfügen, um den letzten Eintrag nach otheridentifier
zu filtern, und dann die obersten drei Zeilen davon übernehmen:
SELECT last.*
FROM `table` last
LEFT JOIN `table` prev
ON prev.`otheridentifier` = last.`otheridentifier`
AND prev.`time` < last.`time`
WHERE prev.`id` is null
ORDER BY last.`time` DESC
LIMIT 3
Ich hatte eine ähnliche Anforderung, hatte jedoch erweiterte Auswahlkriterien. Mit einigen anderen Antworten konnte ich nicht genau das bekommen, was ich brauchte, aber ich fand, dass Sie immer noch eine GROUP BY und ORDER BY so machen können:
SELECT t.* FROM (SELECT * FROM table ORDER BY time DESC) t
GROUP BY t.otheridentifier
SELECT * FROM table t1
WHERE t1.time =
(SELECT MAX(time) FROM table t2
WHERE t2.otheridentifier = t1.otheridentifier)
Andomars Antwort ist wahrscheinlich am besten, da keine Unterabfrage verwendet wird.
Ein alternativer Ansatz:
select *
from `table` t1
where t1.`time` in (
select max(s2.`time`)
from `table` t2
group by t2.otheridentifier
)
Sie können diese Abfrage verwenden, um die richtige Antwort zu erhalten:
SELECT * FROM
(SELECT * FROM `table` order by time DESC)
t group by otheridentifier
wie wäre es mit
SELECT *, max(time) FROM `table` group by otheridentifier
Das auch:
SELECT * FROM
OrigTable T INNER JOIN
(
SELECT otheridentifier,max(time) AS duration
FROM T
GROUP BY otheridentifier) S
ON S.duration = T.time AND S.otheridentifier = T.otheridentifier.