Avec la table MySQL suivante:
+-----------------------------+
+ id INT UNSIGNED +
+ name VARCHAR(100) +
+-----------------------------+
Comment puis-je sélectionner une nique rangée ET sa position parmi les autres rangées du tableau, lorsqu'elles sont triées par name ASC
. Donc, si les données de la table ressemblent à ceci, lorsqu'elles sont triées par nom:
+-----------------------------+
+ id | name +
+-----------------------------+
+ 5 | Alpha +
+ 7 | Beta +
+ 3 | Delta +
+ ..... +
+ 1 | Zed +
+-----------------------------+
Comment pourrais-je sélectionner la rangée Beta
pour obtenir la position actuelle de cette rangée? Le résultat que je recherche devrait ressembler à ceci:
+-----------------------------+
+ id | position | name +
+-----------------------------+
+ 7 | 2 | Beta +
+-----------------------------+
Je peux faire un simple SELECT * FROM tbl ORDER BY name ASC
énumère ensuite les lignes en PHP, mais il semble inutile de charger un ensemble de résultats potentiellement volumineux pour une seule ligne.
Utilisez ceci:
SELECT x.id,
x.position,
x.name
FROM (SELECT t.id,
t.name,
@rownum := @rownum + 1 AS position
FROM TABLE t
JOIN (SELECT @rownum := 0) r
ORDER BY t.name) x
WHERE x.name = 'Beta'
... pour obtenir une valeur de position unique. Cette:
SELECT t.id,
(SELECT COUNT(*)
FROM TABLE x
WHERE x.name <= t.name) AS position,
t.name
FROM TABLE t
WHERE t.name = 'Beta'
... donnera la même valeur aux liens. IE: S'il y a deux valeurs à la deuxième place, elles auront toutes deux une position de 2 lorsque la première requête donnera une position de 2 à l'une d'elles et de 3 à l'autre ...
C’est le seul moyen auquel je puisse penser:
SELECT `id`,
(SELECT COUNT(*) FROM `table` WHERE `name` <= 'Beta') AS `position`,
`name`
FROM `table`
WHERE `name` = 'Beta'
Si la requête est simple et que la taille du jeu de résultats renvoyé est potentiellement importante, vous pouvez essayer de la scinder en deux requêtes.
La première requête avec un critère de filtrage étroit ne sert qu'à extraire les données de cette ligne, et la seconde requête utilise COUNT
avec la clause WHERE
pour calculer la position.
Par exemple dans votre cas
Requête 1:
SELECT * FROM tbl WHERE name = 'Beta'
Requête 2:
SELECT COUNT(1) FROM tbl WHERE name >= 'Beta'
Nous utilisons cette approche dans un tableau avec 2M record, ce qui est bien plus évolutif que l'approche d'OMG Ponies.
J'ai un problème très très similaire, c'est pourquoi je ne poserai pas la même question, mais je vais partager ici ce que j'ai fait, j'ai dû utiliser également un groupe de et l'ordre d'AVG. Il y a des étudiants, avec signatures et socore, et je devais les classer (en d’autres termes, je calcule d’abord le fichier AVG, puis je les commande dans le DESC, puis, finalement, j’ai besoin d’ajouter le poste (classement pour moi). quelque chose très similaire comme le meilleure réponse ici, avec un peu de changements qui s'adaptent à mon problème):
Je mets enfin la colonne position
(rang pour moi) dans le SELECT externe
SET @rank=0;
SELECT @rank := @rank + 1 AS ranking, t.avg, t.name
FROM(SELECT avg(students_signatures.score) as avg, students.name as name
FROM alumnos_materia
JOIN (SELECT @rownum := 0) r
left JOIN students ON students.id=students_signatures.id_student
GROUP BY students.name order by avg DESC) t
La position d'une ligne dans la table représente combien de lignes sont "meilleures" que la ligne ciblée.
Donc, vous devez compter ces lignes.
SELECT COUNT (*) + 1 FROM table
WHERE name
<'Beta'
En cas d'égalité, la position la plus haute est renvoyée.
Si vous ajoutez une autre ligne portant le même nom "Beta" après la ligne "Beta" existante, la position renvoyée serait toujours 2, car elles partageraient la même place dans le classement.
J'espère que cela aidera les personnes qui rechercheront quelque chose de similaire à l'avenir, car je crois que le propriétaire de la question a déjà résolu son problème.
Les autres réponses semblent trop compliquées pour moi.
Voici un exemple simple , disons que vous avez un tableau avec des colonnes:
userid | points
et que vous voulez trier les ID utilisateur par points et obtenir la position de la ligne (le "classement" de l'utilisateur), vous utilisez alors:
SET @row_number = 0;
SELECT
(@row_number:=@row_number + 1) AS num, userid, points
FROM
ourtable
ORDER BY points DESC
num
vous donne la position de la ligne (classement).
Si vous avez MySQL 8.0+, vous pouvez utiliser ROW_NUMBER ()
Je parcourais la réponse acceptée et cela semblait un peu compliqué, donc voici la version simplifiée.
SELECT t,COUNT(*) AS position FROM t
WHERE name <= 'search string' ORDER BY name