Daft SQL-Frage. Ich habe eine Tabelle wie diese ("pid" ist automatisch inkrementelle primäre Spalte)
CREATE TABLE theTable (
`pid` INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
`timestamp` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
`cost` INT UNSIGNED NOT NULL,
`rid` INT NOT NULL,
) Engine=InnoDB;
Aktuelle Tabellendaten:
INSERT INTO theTable (`pid`, `timestamp`, `cost`, `rid`)
VALUES
(1, '2011-04-14 01:05:07', 1122, 1),
(2, '2011-04-14 00:05:07', 2233, 1),
(3, '2011-04-14 01:05:41', 4455, 2),
(4, '2011-04-14 01:01:11', 5566, 2),
(5, '2011-04-14 01:06:06', 345, 1),
(6, '2011-04-13 22:06:06', 543, 2),
(7, '2011-04-14 01:14:14', 5435, 3),
(8, '2011-04-14 01:10:13', 6767, 3)
;
Ich möchte die PID der letzten Zeile für jedes Rid erhalten (1 Ergebnis pro eindeutiger RID). Für die Beispieldaten möchte ich:
pid | MAX(timestamp) | rid
-----------------------------------
5 | 2011-04-14 01:06:06 | 1
3 | 2011-04-14 01:05:41 | 2
7 | 2011-04-14 01:14:14 | 3
Ich habe versucht, die folgende Abfrage auszuführen:
SELECT MAX(timestamp),rid,pid FROM theTable GROUP BY rid
und ich bekomme:
max(timestamp) ; rid; pid
----------------------------
2011-04-14 01:06:06; 1 ; 1
2011-04-14 01:05:41; 2 ; 3
2011-04-14 01:14:14; 3 ; 7
Die zurückgegebene PID ist immer das erste Vorkommen der PID für eine RID (Zeile/PID 1 ist das erste Mal, dass RID 1 verwendet wird, Zeile/PID 3, wenn RID 2 zum ersten Mal verwendet wird; Zeile/PID 7 wird zum ersten Mal, wenn RID 3 verwendet wird ). Obwohl der maximale Zeitstempel für jedes Rid zurückgegeben wird, sind die Pids nicht die Pids für die Zeitstempel aus der Originaltabelle. Welche Abfrage würde mir die gewünschten Ergebnisse liefern?
(Getestet in PostgreSQL 9.etwas)
Identifizieren Sie das Datum und den Zeitstempel.
select rid, max(timestamp) as ts
from test
group by rid;
1 2011-04-14 18:46:00
2 2011-04-14 14:59:00
Mach mit!.
select test.pid, test.cost, test.timestamp, test.rid
from test
inner join
(select rid, max(timestamp) as ts
from test
group by rid) maxt
on (test.rid = maxt.rid and test.timestamp = maxt.ts)
select *
from (
select `pid`, `timestamp`, `cost`, `rid`
from theTable
order by `timestamp` desc
) as mynewtable
group by mynewtable.`rid`
order by mynewtable.`timestamp`
Hoffe ich habe geholfen!
SELECT t.pid, t.cost, to.timestamp, t.rid
FROM test as t
JOIN (
SELECT rid, max(tempstamp) AS maxtimestamp
FROM test GROUP BY rid
) AS tmax
ON t.pid = tmax.pid and t.timestamp = tmax.maxtimestamp
Ich habe einen Index für Rid und Timestamp erstellt.
SELECT test.pid, test.cost, test.timestamp, test.rid
FROM theTable AS test
LEFT JOIN theTable maxt
ON maxt.rid = test.rid
AND maxt.timestamp > test.timestamp
WHERE maxt.rid IS NULL
Zeige Zeilen 0 - 2 (3 gesamt, Abfrage dauerte 0.0104 sec)
Bei dieser Methode werden alle gewünschten Werte aus theTable
(test) ausgewählt, wobei sich der Link (maxt) auf allen Zeitstempeln verbindet, die höher sind als die im Test mit dem gleichen Ergebnis. Wenn der Zeitstempel bereits der höchste im Test ist, gibt es keine Übereinstimmungen bei maxt - was wir suchen - die Werte für maxt werden NULL. Jetzt verwenden wir die WHERE-Klausel maxt.rid IS NULL
oder eine beliebige andere Spalte von maxt.
Wenn Sie ein JOIN vermeiden möchten, können Sie Folgendes verwenden:
SELECT pid, rid FROM theTable t1 WHERE t1.pid IN ( SELECT MAX(t2.pid) FROM theTable t2 GROUP BY t2.rid);
Sie könnten auch solche Unterabfragen haben:
SELECT ( SELECT MIN(t2.pid)
FROM test t2
WHERE t2.rid = t.rid
AND t2.timestamp = maxtimestamp
) AS pid
, MAX(t.timestamp) AS maxtimestamp
, t.rid
FROM test t
GROUP BY t.rid
Auf diese Weise benötigen Sie jedoch eine weitere Unterabfrage, wenn Sie cost
in die angezeigten Spalten usw. aufnehmen möchten.
Daher ist group by
und join
die bessere Lösung.