Récupérer lignes autour d'un offset SQL

Fermé
parousky Messages postés 325 Date d'inscription mardi 11 septembre 2012 Statut Membre Dernière intervention 20 février 2022 - 19 avril 2016 à 11:39
Pitet Messages postés 2826 Date d'inscription lundi 11 février 2013 Statut Membre Dernière intervention 21 juillet 2022 - 19 avril 2016 à 14:30
Bonjour,
dans une requête SQL, j'aimerais retourner une ligne spécifique, plus les quatre lignes autour de cette ligne, de préférence de manière symétrique si possible.
C'est à dire que je récupère la ligne 5, puis les lignes 3-4 et 6-7.

Alors j'ai essayé de me débrouiller avec les OFFSET et LIMIT mais je suis bloqué par le fait que certains identifiants n'existent peut-être pas...
J'ai essayé ça comme code :


$sql = "SELECT * FROM users WHERE ID BETWEEN ? AND ?";
$req = $bdd->prepare($sql);
$req->execute(array($ID-2, $ID+2));



Mais comme je l'ai précisé, si ID = 5 et s'il n'existe pas d'ID 3 et 4 mais juste 1 et 2, ça ne vas pas me retourner les lignes 1 et 2...

Quelqu'un voit-il une solution ?
Merci d'avance pour vos réponses !

2 réponses

Pitet Messages postés 2826 Date d'inscription lundi 11 février 2013 Statut Membre Dernière intervention 21 juillet 2022 526
19 avril 2016 à 12:02
Salut,

Une solution possible :
(SELECT * FROM users WHERE id < 5 ORDER BY id DESC LIMIT 2)
UNION
(SELECT * FROM users WHERE id = 5)
UNION
(SELECT * FROM users WHERE id > 5 ORDER BY id ASC LIMIT 2)
ORDER BY id ASC


Bonne journée,
1
parousky Messages postés 325 Date d'inscription mardi 11 septembre 2012 Statut Membre Dernière intervention 20 février 2022 6
Modifié par parousky le 19/04/2016 à 13:35
Merci pour ta réponse ! Mais en réalité, le problème est un peu plus compliqué.
Admettons que j'ai deux champs dans ma table : ID et Nbre. ID est unique mais pas Nbre (plusieurs utilisateurs peuvent avoir le même Nbre)

Prenons une ligne de la table dont l'ID est ID_0 et le Nbre Nbre_0.

Ce que je veux faire, c'est récupérer les lignes dont Nbre est le plus proche de Nbre_0 mais autour de ID_0.

Pour exemple, le code que tu m'as donné me permet de retourner les lignes dont ID sont les plus proches de ID_0 autour de ID_0.



ID | Nbre
1 | 10
2 | 20
3 | 30
4 | 10
5 | 20
6 | 70
7 | 80
8 | 10
9 | 20
10 | 50

Si ID_0 = 6 (donc Nbre_0 = 70), ça devrait retourner les ID : {7,10,3,2}

J'espère que je ne suis pas trop vague !
0
Pitet Messages postés 2826 Date d'inscription lundi 11 février 2013 Statut Membre Dernière intervention 21 juillet 2022 526
19 avril 2016 à 14:30
Si j'ai bien compris, on devrait pouvoir utiliser la même solution mais en triant les résultats selon la colonne Nbre à la place de ID :
(SELECT * FROM users WHERE id < 6 ORDER BY Nbre DESC LIMIT 2)
UNION
(SELECT * FROM users WHERE id = 6)
UNION
(SELECT * FROM users WHERE id > 6 ORDER BY Nbre ASC LIMIT 2)


Il a néanmoins une ambiguïté sur le fait que plusieurs ID peuvent avoir le même Nbre. En effet en reprenant ton exemple avec ID_0 = 6, les ID retournés devraient être {7,10,3,2} mais pourrait aussi être {7,10,3,5} : les ID 2 et 5 ayant le même Nbre, les deux résultats sont corrects.
Pour annuler cette ambiguïté, on peut ajouter un deuxième tri dans nos requêtes afin de sélectionner les premiers ou les derniers ID qui ont le même Nbre, soit :
(SELECT * FROM users WHERE id < 6 ORDER BY Nbre DESC, id ASC LIMIT 2)
UNION
(SELECT * FROM users WHERE id = 6)
UNION
(SELECT * FROM users WHERE id > 6 ORDER BY Nbre ASC, id ASC LIMIT 2)
ORDER BY id

-> devrait retourner {2,3,6,7,10}

ou
(SELECT * FROM users WHERE id < 6 ORDER BY Nbre DESC, id DESC LIMIT 2)
UNION
(SELECT * FROM users WHERE id = 6)
UNION
(SELECT * FROM users WHERE id > 6 ORDER BY Nbre ASC, id DESC LIMIT 2)

-> devrait retourner {3,5,6,7,10}
0