Question Daft SQL. J'ai une table comme ça ('pid' est l'incrémentation primaire du col primaire)
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;
Données de table réelles:
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)
;
Je veux obtenir le PID de la dernière ligne pour chaque débarras (1 résultat par RID unique). Pour les exemples de données, j'aimerais:
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
J'ai essayé d'exécuter la requête suivante:
SELECT MAX(timestamp),rid,pid FROM theTable GROUP BY rid
et je reçois:
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
Le PID renvoyé est toujours la première apparition de PID pour un RID (row/pid 1 est la première fois que rid 1 est utilisé, row/pid 3 la première fois que le RID 2 est utilisé, row/pid 7 est la première fois que rid 3 est utilisé. ). Bien qu'ils renvoient l'horodatage maximal pour chaque suppression, les pids ne sont pas les pids des horodatages de la table d'origine. Quelle requête me donnerait les résultats que je cherche?
(Testé dans PostgreSQL 9.quelque chose)
Identifiez le débarras et l'horodatage.
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
Rejoignez-le.
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`
J'espère que j'ai aidé!
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
J'ai créé un index sur débarrasser et horodatage.
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
Afficher les lignes 0 - 2 (3 au total, Requête prise en 0.0104 sec)
Cette méthode sélectionnera toutes les valeurs souhaitées parmi theTable
(test), en se laissant se joindre (maxt) sur tous les horodatages supérieurs à celui testé avec le même paramètre. Lorsque l'horodatage est déjà le plus élevé du test, il n'y a pas de correspondance sur maxt - c'est ce que nous recherchons - les valeurs sur maxt deviennent NULL. Nous utilisons maintenant la clause WHERE maxt.rid IS NULL
ou toute autre colonne sur maxt.
Si vous voulez éviter une jointure, vous pouvez utiliser:
SELECT pid, rid FROM theTable t1 WHERE t1.pid IN ( SELECT MAX(t2.pid) FROM theTable t2 GROUP BY t2.rid);
Vous pourriez aussi avoir des sous-requêtes comme ça:
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
Mais de cette façon, vous aurez besoin d’une sous-requête supplémentaire si vous souhaitez que cost
soit inclus dans les colonnes affichées, etc.
Donc, group by
et join
est la meilleure solution.