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

parousky Messages postés 325 Date d'inscription   Statut Membre Dernière intervention   -  
Pitet Messages postés 2826 Date d'inscription   Statut Membre Dernière intervention   -
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   Statut Membre Dernière intervention   527
 
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   Statut Membre Dernière intervention   6
 
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   Statut Membre Dernière intervention   527
 
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