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`
3 Réponses :
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;
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;
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.
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. 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;
Oui, vous pouvez utiliser l'instruction
casedans l'ordre par clause