j'ai une table comme celle-ci:
name date time
tom | 2011-07-04 | 01:09:52
tom | 2011-07-04 | 01:09:52
mad | 2011-07-04 | 02:10:53
mad | 2009-06-03 | 00:01:01
je veux le nom le plus ancien en premier:
SELECT *
ORDER BY date ASC, time ASC
GROUP BY name
(-> ne fonctionne pas!)
maintenant il devrait me donner d'abord folle (date antérieure) puis tom
mais avec GROUP BY name ORDER BY date ASC, time ASC
me donne le nouveau fou en premier parce qu'il se groupe avant de trier!
encore une fois: le problème est que je ne peux pas trier par date et heure avant de me regrouper car GROUP BY doit être avant ORDER BY!
Une autre méthode:
SELECT *
FROM (
SELECT *
ORDER BY date ASC, time ASC
) AS sub
GROUP BY name
GROUP BY sur le premier résultat correspondant atteint. Si ce premier résultat correspondant s'avère être celui que vous voulez, tout devrait fonctionner comme prévu.
Je préfère cette méthode car la sous-requête a un sens logique plutôt que de la combiner avec d'autres conditions.
Je pense que c'est ce que vous recherchez:
SELECT name, min(date)
FROM myTable
GROUP BY name
ORDER BY min(date)
Pour le moment, vous devez créer une date mysql via STR_TO_DATE:
STR_TO_DATE(date + ' ' + time, '%Y-%m-%d %h:%i:%s')
Alors :
SELECT name, min(STR_TO_DATE(date + ' ' + time, '%Y-%m-%d %h:%i:%s'))
FROM myTable
GROUP BY name
ORDER BY min(STR_TO_DATE(date + ' ' + time, '%Y-%m-%d %h:%i:%s'))
Comme je ne suis pas autorisé à commenter la réponse de user1908688, voici un indice pour les utilisateurs de MariaDB:
SELECT *
FROM (
SELECT *
ORDER BY date ASC, time ASC
LIMIT 18446744073709551615
) AS sub
GROUP BY sub.name
https://mariadb.com/kb/en/mariadb/why-is-order-by-in-a-from-subquery-ignored/
Cela a fonctionné pour moi:
SELECT *
FROM your_table
WHERE id IN (
SELECT MAX(id)
FROM your_table
GROUP BY name
);
Utilisez une sous-sélection:
select name, date, time
from mytable main
where date + time = (select min(date + time) from mytable where name = main.mytable)
order by date + time;
J'avais une variante différente de cette question où je n'avais qu'un seul champ DATETIME
et j'avais besoin d'un limit
après un group by
ou d'un distinct
après avoir trié par ordre décroissant en fonction du champ datetime
, mais c'est ce qui m'a aidé:
select distinct (column) from
(select column from database.table
order by date_column DESC) as hist limit 10
Dans cet exemple avec les champs divisés, si vous pouvez trier sur un concat, vous pourrez peut-être vous en tirer avec quelque chose comme:
select name,date,time from
(select name from table order by concat(date,' ',time) ASC)
as sorted
Ensuite, si vous voulez limiter, vous ajouterez simplement votre déclaration de limite à la fin:
select name,date,time from
(select name from table order by concat(date,' ',time) ASC)
as sorted limit 10
Un autre moyen de résoudre ce problème serait d'utiliser un LEFT JOIN
, qui pourrait être plus efficace. Commençons par un exemple prenant en compte uniquement le champ de date, car il est probablement plus courant de stocker date + heure dans une colonne datetime. Je souhaite également que la requête soit simple afin de la rendre plus facile à comprendre.
Ainsi, avec cet exemple particulier, si vous souhaitez afficher l'enregistrement plus ancien en fonction de la colonne date, et en supposant que le nom de votre table s'appelle people
, vous pouvez utiliser la requête suivante:
SELECT p.* FROM people p
LEFT JOIN people p2 ON p.name = p2.name AND p.date > p2.date
WHERE p2.date is NULL
GROUP BY p.name
Ce que le LEFT JOIN
fait, c’est lorsque la colonne p.date
est à sa valeur minimale, il n’y aura pas de p2.date
avec une valeur plus petite dans la jointure de gauche et le p2.date
correspondant sera donc NULL
. Donc, en ajoutant WHERE p2.date is NULL
, nous nous assurons d’afficher uniquement les enregistrements avec la date la plus ancienne.
De même, si vous souhaitez afficher l’enregistrement latest à la place, vous pouvez simplement modifier l’opérateur de comparaison dans le LEFT JOIN
:
SELECT p.* FROM people p
LEFT JOIN people p2 ON p.name = p2.name AND p.date < p2.date
WHERE p2.date is NULL
GROUP BY p.name
Maintenant, pour cet exemple particulier où date + heure sont des colonnes séparées, vous devrez les ajouter si vous souhaitez interroger en fonction de la date/heure de deux colonnes combinées, par exemple:
SELECT p.* FROM people p
LEFT JOIN people p2 ON p.name = p2.name AND p.date + INTERVAL TIME_TO_SEC(p.time) SECOND > p2.date + INTERVAL TIME_TO_SEC(p2.time) SECOND
WHERE p2.date is NULL
GROUP BY p.name
Vous pouvez en savoir plus à ce sujet (et voir d’autres moyens de le faire) à la page Les lignes contenant le maximum groupe de certaines colonnes .