Ma table est:
id home datetime player resource
---|-----|------------|--------|---------
1 | 10 | 04/03/2009 | john | 399
2 | 11 | 04/03/2009 | juliet | 244
5 | 12 | 04/03/2009 | borat | 555
3 | 10 | 03/03/2009 | john | 300
4 | 11 | 03/03/2009 | juliet | 200
6 | 12 | 03/03/2009 | borat | 500
7 | 13 | 24/12/2008 | borat | 600
8 | 13 | 01/01/2009 | borat | 700
J'ai besoin de sélectionner chaque home
contenant distinct la valeur maximale de datetime
.
Le résultat serait:
id home datetime player resource
---|-----|------------|--------|---------
1 | 10 | 04/03/2009 | john | 399
2 | 11 | 04/03/2009 | juliet | 244
5 | 12 | 04/03/2009 | borat | 555
8 | 13 | 01/01/2009 | borat | 700
J'ai essayé:
-- 1 ..by the MySQL manual:
SELECT DISTINCT
home,
id,
datetime AS dt,
player,
resource
FROM topten t1
WHERE datetime = (SELECT
MAX(t2.datetime)
FROM topten t2
GROUP BY home)
GROUP BY datetime
ORDER BY datetime DESC
Ça ne marche pas. L'ensemble de résultats contient 130 lignes, bien que la base de données en contienne 187. Le résultat inclut des doublons de home
.
-- 2 ..join
SELECT
s1.id,
s1.home,
s1.datetime,
s1.player,
s1.resource
FROM topten s1
JOIN (SELECT
id,
MAX(datetime) AS dt
FROM topten
GROUP BY id) AS s2
ON s1.id = s2.id
ORDER BY datetime
Nan. Donne tous les enregistrements.
-- 3 ..something exotic:
Avec différents résultats.
id
,player
etresource
de la ligne non max pour une maison donnée, c'est-à-dire pour la maison = 10, vous pouvez obtenir:3 | 10 | 04/03/2009 | john | 300
En d'autres termes, cela ne garantit pas que toutes les colonnes d'une ligne du jeu de résultats appartiendront à max (datetime) pour une maison donnée.La
MySQL
solution la plus rapide , sans requêtes internes et sansGROUP BY
:Explication :
Rejoignez le tableau avec lui-même en utilisant la
home
colonne. L'utilisation deLEFT JOIN
garantit que toutes les lignes du tableaum
apparaissent dans le jeu de résultats. Ceux qui n'ont pas de correspondance dans le tableaub
aurontNULL
s pour les colonnes deb
.L'autre condition sur le
JOIN
demande de faire correspondre uniquement les lignes deb
qui ont une plus grande valeur sur ladatetime
colonne que la ligne dem
.En utilisant les données publiées dans la question, le
LEFT JOIN
produira ces paires:Enfin, la
WHERE
clause ne conserve que les paires qui ontNULL
s dans les colonnes deb
(elles sont marquées avec*
dans le tableau ci-dessus); cela signifie qu'en raison de la deuxième condition de laJOIN
clause, la ligne sélectionnéem
a la plus grande valeur dans la colonnedatetime
.Lisez le livre SQL Antipatterns: Éviter les pièges de la programmation de base de données pour d'autres conseils SQL.
la source
SQLite
, la première est beaucoup plus lente que la version de La Voie quand il n'y a pas d'index sur la colonne correspondante (ie "home"). (Testé avec 24k lignes résultant en 13k lignes)home
etdatetime
etdatetime
est le maximum pour ce particulierhome
?ON
clause. Fe... ON ... AND m.id < b.id
pour conserver l'entrée la plus récente (celle avec la plus grandeid
) lorsque deux lignes ont les mêmes valeurs danshome
etdatetime
colonnes et que c'est le maximumdatetime
.Voici la version T-SQL :
EDIT
Malheureusement, il n'y a pas de fonction RANK () OVER dans MySQL.
Mais il peut être émulé, voir Émulation de fonctions analytiques (classement AKA) avec MySQL .
Donc , c'est MySQL version:
la source
Cela fonctionnera même si vous avez deux lignes ou plus pour chacune
home
avec des égalesDATETIME
:la source
WHERE ti.home = t1.home
- pouvez-vous expliquer la syntaxe?select
requête qui a la ligneWHERE ti.home = t1.home
n'a pas besoin de laFROM
clause qui définitt1
. Alors, comment est-il utilisé?Je pense que cela vous donnera le résultat souhaité:
MAIS si vous avez également besoin d'autres colonnes, faites simplement une jointure avec la table d'origine (vérifiez la
Michael La Voie
réponse)Meilleures salutations.
la source
Étant donné que les gens semblent continuer à courir dans ce fil (la date des commentaires varie de 1,5 an), ce n'est pas beaucoup plus simple:
SELECT * FROM (SELECT * FROM topten ORDER BY datetime DESC) tmp GROUP BY home
Aucune fonction d'agrégation nécessaire ...
À votre santé.
la source
Vous pouvez également essayer celui-ci et pour les grandes tables, les performances des requêtes seront meilleures. Cela fonctionne quand il n'y a pas plus de deux enregistrements pour chaque maison et que leurs dates sont différentes. Une meilleure requête générale MySQL est celle de Michael La Voie ci-dessus.
Ou en cas de Postgres ou de ces dbs qui fournissent des fonctions analytiques, essayez
la source
SQLite
, la première est beaucoup plus lente que la version de La Voie quand il n'y a pas d'index sur la colonne correspondante (ie "home").Cela fonctionne sur Oracle:
la source
la source
Essayez ceci pour SQL Server:
la source
la source
Voici la version de MySQL qui imprime une seule entrée où il y a des doublons MAX (datetime) dans un groupe.
Vous pouvez tester ici http://www.sqlfiddle.com/#!2/0a4ae/1
Exemples de données
Version MySQL avec variable utilisateur
Réponses acceptées
la source
Une autre façon de gt la ligne la plus récente par groupe en utilisant une sous-requête qui calcule essentiellement un classement pour chaque ligne par groupe, puis filtrez vos lignes les plus récentes comme avec rank = 1
DEMO
Voici la démo visuelle du rang no pour chaque ligne pour une meilleure compréhension
La requête ci-dessus échouera et renverra plus de 1 lignes pour la situation ci-dessus. Pour couvrir cette situation, il faudra un autre critère / paramètre / colonne pour décider quelle ligne doit être prise et qui tombe dans la situation ci-dessus. En consultant l'échantillon de données, je suppose qu'il existe une colonne de clé primaire
id
qui doit être définie sur incrémentation automatique. Nous pouvons donc utiliser cette colonne pour choisir la ligne la plus récente en modifiant la même requête à l'aide d'uneCASE
instruction commeDEMO
La requête ci-dessus sélectionnera la ligne avec l'ID le plus élevé parmi les mêmes
datetime
valeursdémo visuelle pour le rang no pour chaque ligne
la source
Pourquoi ne pas utiliser: SELECT home, MAX (datetime) AS MaxDateTime, player, resource FROM topten GROUP BY home A-t-il manqué quelque chose?
la source
expected
sortie dans MySQL version 5.6before
et je doute fortement qu'elle se comporte autrement dans MySQL version 5.7 etafter
.Essaye ça
Cordialement K
la source
max(datetime)
isdatetime
. Cela ne posera-t-il aucun problème?datetime
sélectionné?c'est la requête dont vous avez besoin:
la source
@Michae La réponse acceptée fonctionnera très bien dans la plupart des cas, mais elle échoue pour l'un comme ci-dessous.
Dans le cas où il y avait 2 lignes ayant HomeID et Datetime identiques, la requête retournera les deux lignes, pas HomeID différent comme requis, pour cela ajouter Distinct dans la requête comme ci-dessous.
la source
J'espère que la requête ci-dessous donnera la sortie souhaitée:
la source