1
votes

Y a-t-il une fonctionnalité dans mysql pour trier par ligne spécifique?

J'ai une table par exemple des étudiants:

id |  name
---|------
1  | A
2  | B
3  | C
4  | D
8  | H
7  | G
6  | F
5  | E

Comment écrire un sql dans mysql pour que les 4 premiers étudiants soient triés par id croissant et ordre de repos par id décroissant La sortie devrait être quelque chose comme ça

 id | name
 -- |-----
 1  | A
 2  | B
 3  | C
 4  | D
 5  | E
 6  | F
 7  | G
 8  | H`


1 commentaires

Oui, vous pouvez utiliser l'instruction case dans l'ordre par clause


3 Réponses :


3
votes

Vous utilisez une version de MySQL antérieure à 8+, ce qui signifie que vous ne pouvez pas utiliser de fonctions analytiques ici. Voici une façon de faire cela, en utilisant une sous-requête corrélée avec une expression CASE :

SELECT t1.id, t1.name
FROM yourTable t1
ORDER BY
    CASE WHEN ROW_NUMBER() OVER (ORDER BY id) <= 4 THEN 0 ELSE 1 END,
    CASE WHEN ROW_NUMBER() OVER (ORDER BY id) <= 4 THEN id ELSE -id END;

 entrez la description de l'image ici p >

Démo

La raison pour laquelle je calcule le numéro de ligne ci-dessus avec une sous-requête corrélée, plutôt que d'utiliser simplement l ' id , est que peut-être que vos valeurs id ne commencent pas toujours à 1 , voire être contigus. Le numéro de ligne peut toujours cibler correctement les enregistrements de première ligne, comme triés par id , tandis que la valeur de id elle-même peut ne pas toujours suffire. p>

Notez que les fonctions analytiques rendent le code beaucoup plus facile à lire ici. Voici ce que vous pouvez faire avec MySQL 8+:

SELECT t1.id, t1.name
FROM yourTable t1
ORDER BY
    CASE WHEN (SELECT COUNT(*) FROM yourTable t2 WHERE t2.id <= t1.id) <= 4
         THEN 0
         ELSE 1 END,
    CASE WHEN (SELECT COUNT(*) FROM yourTable t2 WHERE t2.id <= t1.id) <= 4
         THEN id
         ELSE -id END;


2 commentaires

Je déconseille fortement la première approche. L'utilisation d'une sous-requête corrélée pour énumérer les lignes est très coûteuse. Si vous utilisez MySQL 8+, alors row_number () est une très bonne solution.


@GordonLinoff Et je suis d'accord avec vous. Si l'OP a de telles exigences à long terme, la mise à niveau / le passage à une base de données qui prend en charge les fonctions analytiques de base pourrait être en ordre.



1
votes

Vous pouvez utiliser une sous-requête corrélée pour calculer le "rang" de la ligne. Le tri est simple:

SELECT *, (SELECT COUNT(*) FROM t AS x WHERE id < t.id) AS rn
FROM t
ORDER BY CASE WHEN rn >= 4 THEN -rn END, rn
  • SELECT COUNT (*) FROM t AS x WHERE id attribue des numéros consécutifs à chaque ligne à partir de 0
  • CASE WHEN rn> = 4 THEN -rn END affecte NULL au rang numéro 0 ... 3 donc un tri secondaire est nécessaire.


0 commentaires

0
votes

Sur la base de vos exemples de données, la méthode la plus simple serait:

select s.*
from students s cross join
     (select s2.id
      from students s2
      order by s2.id
      limit 3, 1
     ) as s4
order by (case when s.id <= s4.id then 1 else 2 end),
         (case when s.id <= s4.id then s.id end),
         s.name desc;

Si vous ne savez pas où se trouve le quatrième identifiant, alors:

order by (case when id <= 4 then 1 else 2 end),
         (case when id <= 4 then id end),
         name desc;


0 commentaires