J'ai un tableau ("lms_attendance") des heures d'enregistrement et de départ des utilisateurs qui ressemble à ceci:
id user time io (enum)
1 9 1370931202 out
2 9 1370931664 out
3 6 1370932128 out
4 12 1370932128 out
5 12 1370933037 in
J'essaie de créer une vue de cette table qui ne produirait que l'enregistrement le plus récent par identifiant d'utilisateur, tout en me donnant la valeur "in" ou "out", ainsi:
id user time io
2 9 1370931664 out
3 6 1370932128 out
5 12 1370933037 in
Je suis assez proche jusqu'à présent, mais j'ai compris que les vues n'acceptaient pas les sous-requêtes, ce qui rend la tâche beaucoup plus difficile. La requête la plus proche que j'ai eu était:
select
`lms_attendance`.`id` AS `id`,
`lms_attendance`.`user` AS `user`,
max(`lms_attendance`.`time`) AS `time`,
`lms_attendance`.`io` AS `io`
from `lms_attendance`
group by
`lms_attendance`.`user`,
`lms_attendance`.`io`
Mais ce que je reçois c'est:
id user time io
3 6 1370932128 out
1 9 1370931664 out
5 12 1370933037 in
4 12 1370932128 out
Ce qui est proche, mais pas parfait. Je sais que le dernier groupe de ne devrait pas être là, mais sans lui, il renvoie l'heure la plus récente, mais pas avec sa valeur relative IO.
Des idées? Merci!
Requete:
SELECT t1.*
FROM lms_attendance t1
WHERE t1.time = (SELECT MAX(t2.time)
FROM lms_attendance t2
WHERE t2.user = t1.user)
Résultat:
| ID | USER | TIME | IO |
--------------------------------
| 2 | 9 | 1370931664 | out |
| 3 | 6 | 1370932128 | out |
| 5 | 12 | 1370933037 | in |
Solution qui va marcher à chaque fois:
SELECT t1.*
FROM lms_attendance t1
WHERE t1.id = (SELECT t2.id
FROM lms_attendance t2
WHERE t2.user = t1.user
ORDER BY t2.id DESC
LIMIT 1)
Inutile d'essayer de réinventer la roue, car c'est courant problème du plus grand nombre par groupe . Very Nice la solution est présentée .
Je préfère la solution la plus simpliste ( voir SQLFiddle, Justin's mis à jour ) sans sous-requêtes (donc facile à utiliser dans les vues):
SELECT t1.*
FROM lms_attendance AS t1
LEFT OUTER JOIN lms_attendance AS t2
ON t1.user = t2.user
AND (t1.time < t2.time
OR (t1.time = t2.time AND t1.Id < t2.Id))
WHERE t2.user IS NULL
Cela fonctionne également dans le cas où il y a deux enregistrements différents avec la même plus grande valeur dans le même groupe - grâce à l'astuce avec (t1.time = t2.time AND t1.Id < t2.Id)
. Tout ce que je fais ici est d’assurer que dans le cas où deux enregistrements du même utilisateur ont le même temps, un seul est choisi. Peu importe si le critère est Id
ou quelque chose d’autre - en principe, tout critère dont l’unicité est garantie rendrait le travail ici.
Basé sur @TMS answer, j'aime bien parce qu'il n'y a pas besoin de sous-requêtes mais je pense qu'omettre la partie 'OR'
sera suffisant et beaucoup plus simple à comprendre et à lire.
SELECT t1.*
FROM lms_attendance AS t1
LEFT JOIN lms_attendance AS t2
ON t1.user = t2.user
AND t1.time < t2.time
WHERE t2.user IS NULL
si vous n'êtes pas intéressé par les lignes avec des temps nuls, vous pouvez les filtrer dans la clause WHERE
:
SELECT t1.*
FROM lms_attendance AS t1
LEFT JOIN lms_attendance AS t2
ON t1.user = t2.user
AND t1.time < t2.time
WHERE t2.user IS NULL and t1.time IS NOT NULL
Déjà résolu, mais pour le compte rendu, une autre approche serait de créer deux vues ...
CREATE TABLE lms_attendance
(id int, user int, time int, io varchar(3));
CREATE VIEW latest_all AS
SELECT la.user, max(la.time) time
FROM lms_attendance la
GROUP BY la.user;
CREATE VIEW latest_io AS
SELECT la.*
FROM lms_attendance la
JOIN latest_all lall
ON lall.user = la.user
AND lall.time = la.time;
INSERT INTO lms_attendance
VALUES
(1, 9, 1370931202, 'out'),
(2, 9, 1370931664, 'out'),
(3, 6, 1370932128, 'out'),
(4, 12, 1370932128, 'out'),
(5, 12, 1370933037, 'in');
SELECT * FROM latest_io;
Essayez cette requête:
select id,user, max(time), io
FROM lms_attendance group by user;
Ok, cela peut être un hack ou une erreur, mais de toute façon cela fonctionne aussi bien.
SELECT id, MAX(user) as user, MAX(time) as time, MAX(io) as io FROM lms_attendance GROUP BY id;
select b.* from
(select
`lms_attendance`.`user` AS `user`,
max(`lms_attendance`.`time`) AS `time`
from `lms_attendance`
group by
`lms_attendance`.`user`) a
join
(select *
from `lms_attendance` ) b
on a.user = b.user
and a.time = b.time
select result from (
select vorsteuerid as result, count(*) as anzahl from kreditorenrechnung where kundeid = 7148
group by vorsteuerid
) a order by anzahl desc limit 0,1