1
votes

MySQL obtient des lignes commençant par un identifiant spécifique après le tri / ordre par

J'ai ce tableau:

6  | 2
9  | 2
1  | 1

Je dois le classer par score desc:

id | score
2  | 4
3  | 4
8  | 4
4  | 3
10 | 3
5  | 2
6  | 2
9  | 2
1  | 1
7  | 1

et obtenir les 3 premières lignes qui commencent avec id 6

Le résultat devrait donc être:

id | score
1  | 1
2  | 4
3  | 4
4  | 3
5  | 2
6  | 2
7  | 1
8  | 4
9  | 2
10 | 3

Est-ce possible? Merci d'avance


0 commentaires

3 Réponses :


2
votes

J'aborderais cela avec un sum () cumulatif (disponible dans MySQL 8.0):

select 
    id, 
    score
from 
  (select @sm := 0) s
  cross join (select id, score from mytable order by score desc, id) t
order by 
    case when id = 6 then @sm := @sm + 1 end desc, 
    score desc,
    id
limit 3

Les commandes sum () enregistrer dans la direction requise; dès que l'enregistrement qui a id = 6 est atteint, la somme prend la valeur 1 . Cela permet de mettre ces enregistrements au top. Le reste consiste simplement à ajouter les critères de tri supplémentaires et à limiter le nombre de résultats.

Démo sur DB Fiddle :

| id  | score |
| --- | ----- |
| 6   | 2     |
| 9   | 2     |
| 1   | 1     |

Dans les versions antérieures de mysql, vous pouvez émuler la somme des fenêtres avec une variable utilisateur, comme suit:

select 
    id, 
    score
from mytable
order by 
    sum(id = 6) over(order by score desc, id) desc, 
    score desc,
    id
limit 3

Démo sur DB Fiddle : mêmes résultats


2 commentaires

J'aime ta première solution.


@GordonLinoff: très apprécié ... Merci!



1
votes

Avec cette table

id  score
8   4
4   3
10  3

Et cette sélection

SELECT `id`, `score`
FROM (SELECT `id`,`score`,if (id = 8,@scoreid:= @scoreid +1,@scoreid) scoreid
       From table3, (SELECT @scoreid :=0) s  Order by score desc) t1 
Where scoreid > 0 LIMIT 3;

vous obtenez

CREATE TABLE table3
    (`id` int, `score` int)
;

INSERT INTO table3
    (`id`, `score`)
VALUES
    (1, 1),
    (2, 4),
    (3, 4),
    (4, 3),
    (5, 2),
    (6, 2),
    (7, 1),
    (8, 4),
    (9, 2),
    (10, 3)
;

Exemple de DBFiddle https://dbms=mysql_5.7&fiddle=95e2051d560c2ac27fdcc8f9d04acf5d" rel="nofollow noreferrer"> https://dbms=mysql_5.7&fiddle=95e2051d560c2ac27fdcc8f9d04acf5d" rel="nofollow noreferrer"> https://dbiddleccfiddle.uk/?rdbms=mysqf5l4c4cf_ac279dbms7&f51cdfiddle.uk/? / a>


1 commentaires

J'ai dû le décocher, cela ne fonctionne pas quand j'essaie d'obtenir 5 lignes commençant par id 8, mais la solution @forpas fonctionne



1
votes

Avec ceci:

| id  | score |
| --- | ----- |
| 6   | 2     |
| 9   | 2     |
| 1   | 1     |

Voir la démo .
Résultats:

select t.*
from tablename t cross join (select * from tablename where id = 6) c
where t.score < c.score or (t.score = c.score and t.id >= c.id)
order by t.score desc, t.id
limit 3


5 commentaires

Merci! C'est la meilleure solution


@EduardUnruh vérifie une version modifiée du code où vous ne devez spécifier 6 qu'une seule fois.


Agréable! Mais j'ai une autre question: y a-t-il un moyen de trier le score desc, id desc avant d'obtenir 3 lignes commençant par id 6? J'ai essayé en ajoutant "desc" après t.id et obtenir l'ID 9,6,7 mais ça devrait être 6,5,7


Si je comprends bien, cela fera: sélectionnez t. * À partir de nomtable t jointure croisée (sélectionnez * à partir de nomtable où id = 6) c où t.score


Parfait merci encore !! Les heures de réflexion sur la façon de résoudre mes besoins en ajoutant des tonnes de code inutile avant et après les requêtes sont terminées: D