Est-il possible d'obtenir le numéro de ligne réel d'une requête?
Je veux pouvoir commander une table appelée league_girl par un champ appelé score; et renvoie le nom d'utilisateur et la position réelle de ce nom d'utilisateur.
Je veux classer les utilisateurs afin que je puisse dire où un utilisateur particulier est, à savoir. Joe occupe la position 100 sur 200, c’est-à-dire.
User Score Row
Joe 100 1
Bob 50 2
Bill 10 3
J'ai déjà vu quelques solutions, mais j'ai essayé la plupart d'entre elles et aucune d'elles ne renvoie le numéro de ligne.
J'ai essayé ceci:
SELECT position, username, score
FROM (SELECT @row := @row + 1 AS position, username, score
FROM league_girl GROUP BY username ORDER BY score DESC)
Comme dérivé
... mais il ne semble pas retourner la position de la ligne.
Des idées?
Vous voudrez peut-être essayer ce qui suit:
SELECT l.position,
l.username,
l.score,
@curRow := @curRow + 1 AS row_number
FROM league_girl l
JOIN (SELECT @curRow := 0) r;
La partie JOIN (SELECT @curRow := 0)
autorise l'initialisation de la variable sans nécessiter une commande SET
séparée.
Cas de test:
CREATE TABLE league_girl (position int, username varchar(10), score int);
INSERT INTO league_girl VALUES (1, 'a', 10);
INSERT INTO league_girl VALUES (2, 'b', 25);
INSERT INTO league_girl VALUES (3, 'c', 75);
INSERT INTO league_girl VALUES (4, 'd', 25);
INSERT INTO league_girl VALUES (5, 'e', 55);
INSERT INTO league_girl VALUES (6, 'f', 80);
INSERT INTO league_girl VALUES (7, 'g', 15);
Requête de test:
SELECT l.position,
l.username,
l.score,
@curRow := @curRow + 1 AS row_number
FROM league_girl l
JOIN (SELECT @curRow := 0) r
WHERE l.score > 50;
Résultat:
+----------+----------+-------+------------+
| position | username | score | row_number |
+----------+----------+-------+------------+
| 3 | c | 75 | 1 |
| 5 | e | 55 | 2 |
| 6 | f | 80 | 3 |
+----------+----------+-------+------------+
3 rows in set (0.00 sec)
SELECT @i:=@i+1 AS iterator, t.*
FROM tablename t,(SELECT @i:=0) foo
Voici la structure de modèle que j'ai utilisée:
select
/*this is a row number counter*/
( select @rownum := @rownum + 1 from ( select @rownum := 0 ) d2 )
as rownumber,
d3.*
from
( select d1.* from table_name d1 ) d3
Et voici mon code de travail:
select
( select @rownum := @rownum + 1 from ( select @rownum := 0 ) d2 )
as rownumber,
d3.*
from
( select year( d1.date ), month( d1.date ), count( d1.id )
from maindatabase d1
where ( ( d1.date >= '2013-01-01' ) and ( d1.date <= '2014-12-31' ) )
group by YEAR( d1.date ), MONTH( d1.date ) ) d3
Vous pouvez aussi utiliser
SELECT @curRow := ifnull(@curRow,0) + 1 Row, ...
pour initialiser la variable compteur.
Si vous souhaitez simplement connaître la position d'un utilisateur spécifique après le classement par score de champ, vous pouvez simplement sélectionner toutes les lignes de votre tableau où le score de champ est supérieur au score de l'utilisateur actuel. Et utilisez le numéro de ligne renvoyé + 1 pour savoir quelle position de cet utilisateur actuel.
En supposant que votre table est "league_girl" et que votre champ principal soit "id", vous pouvez utiliser ceci:
SELECT count(id) + 1 as rank from league_girl where score > <your_user_score>
En supposant que MySQL le supporte, vous pouvez facilement le faire avec une sous-requête SQL standard:
select
(count(*) from league_girl l1 where l2.score > l1.score and l1.id <> l2.id) as position,
username,
score
from league_girl l2
order by score;
Pour les grandes quantités de résultats affichés, cela sera un peu lent et vous voudrez plutôt passer à une auto-jointure.
Je sais que le PO demande une réponse mysql
, mais comme j'ai trouvé les autres réponses ne fonctionnaient pas pour moi,
order by
Donc, pour gagner du temps pour des gens comme moi, indexez simplement la ligne après l'avoir extraite de la base de données
exemple en PHP:
$users = UserRepository::loadAllUsersAndSortByScore();
foreach($users as $index=>&$user){
$user['rank'] = $index+1;
}
exemple dans PHP en utilisant offset et limit pour la pagination:
$limit = 20; //page size
$offset = 3; //page number
$users = UserRepository::loadAllUsersAndSortByScore();
foreach($users as $index=>&$user){
$user['rank'] = $index+1+($limit*($offset-1));
}
J'ai trouvé la réponse originale extrêmement utile, mais je souhaitais également saisir un certain ensemble de lignes en fonction des numéros de ligne que j'inscrivais. En tant que tel, j'ai encapsulé la réponse originale complète dans une sous-requête afin de pouvoir référencer le numéro de ligne que j'étais en train d'insérer.
SELECT * FROM
(
SELECT *, @curRow := @curRow + 1 AS "row_number"
FROM db.tableName, (SELECT @curRow := 0) r
) as temp
WHERE temp.row_number BETWEEN 1 and 10;
Avoir une sous-requête dans une sous-requête n'est pas très efficace, il serait donc intéressant de vérifier si vous obtenez un meilleur résultat en laissant votre serveur SQL gérer cette requête, ou en récupérant la table entière et en laissant l'application/le serveur Web manipuler les lignes après coup. .
Personnellement, mon serveur SQL n'est pas trop occupé, il était donc préférable de gérer les sous-requêtes imbriquées.