Page 1 sur 2
faire une selection 10 lignes avant et apres une valeur
Posté : 17 avr. 2007, 16:27
par Snoops
Bonjour,
Je précise que je suis sous SQL Server ...
Je souhaiterais soumettre une requete au serveur afin qu'il m'affiche les n lignes précédentes, et les n lignes suivantes, entourant une occurence passée en paramètre.
Exemple :
ID | Nom | Prenom
1 | A | a
2 | B | b
3 | C | c
4 | D | d
5 | E | e
6 | F | f
7 | G | g
8 | H | h
9 | I | i
10 | J | j
après ma requete je voudrais voir s'afficher les 3 résultats au dessus et en dessous de l'ID=5 :
2 | B | b
3 | C | c
4 | D | d
5 | E | e
6 | F | f
7 | G | g
8 | H | h
Je ne sais pas si je me fais bien comprendre ...
Merci
Posté : 17 avr. 2007, 19:07
par Hubert Roksor
Difficile à dire comme ça, comment sont classés les résultats ?
Posté : 17 avr. 2007, 19:08
par Snoops
Difficile à dire comme ça, comment sont classés les résultats ?
par l'id en question. Mais au pire ca se modifie dans le ORDER BY.
Posté : 17 avr. 2007, 19:10
par Hubert Roksor
Err... je vais reformuler. Qu'est-ce qui t'empêche de faire "...WHERE id BETWEEN 1 AND 9" si tu sais que l'ID du milieu est 5 ?
Le plus simple serait probablement de nous montrer la requête qui te renvoit le classement complet.
Posté : 17 avr. 2007, 19:13
par Snoops
Err... je vais reformuler. Qu'est-ce qui t'empêche de faire "...WHERE id BETWEEN 1 AND 9" si tu sais que l'ID du milieu est 5 ?
alors effectivement, j'ai pas été assez précis ... mes ID ne sont pas des nombres, mais des caracteres, plus exactement "nom.premiere_lettre_prenom". Désolé.
Posté : 17 avr. 2007, 19:28
par Hubert Roksor
Pas de problème, on avance
Est-ce que tu pourrais me montrer la requête qui renvoit le classement complet ainsi que la valeur de référence (celle du milieu de la "section" de classement) et la colonne à laquelle elle correspond ?
Je suis une nouille sous SQL Server, mais la solution est soit une procédure avec un curseur soit deux SELECT avec une UNION. Ou encore une table dérivée, mais je ne peux pas prédire les perfs. Il parait que l'optimiseur de SQL Server est puissant, mais c'est un cas assez spécial, je ne suis pas certain qu'il l'optimise parfaitement. Dès que je comprends exactement ce que tu veux faire je te donnerai quelques pistes à explorer.
Ah pis aussi la taille de la table, ça peut décider de la voie à emprunter.
Posté : 17 avr. 2007, 19:36
par Snoops
Pas de problème, on avance
Est-ce que tu pourrais me montrer la requête qui renvoit le classement complet ainsi que la valeur de référence (celle du milieu de la "section" de classement) et la colonne à laquelle elle correspond ?
Je suis une nouille sous SQL Server, mais la solution est soit une procédure avec un curseur soit deux SELECT avec une UNION. Ou encore une table dérivée, mais je ne peux pas prédire les perfs. Il parait que l'optimiseur de SQL Server est puissant, mais c'est un cas assez spécial, je ne suis pas certain qu'il l'optimise parfaitement. Dès que je comprends exactement ce que tu veux faire je te donnerai quelques pistes à explorer
Je ne mets pas toute la table le reste ne te servirais a rien, mais voici la structure :
Code : Tout sélectionner
CREATE TABLE Employe
(
id_employe VARCHAR(40) NOT NULL,
nom_employe VARCHAR(30) NOT NULL,
prenom_employe VARCHAR(30) NOT NULL,
...
PRIMARY KEY (id_employe),
...
);
Quant à la requete elle est pour le moment basique (j'affiche tout) :
Code : Tout sélectionner
SELECT id_employe, nom_employe, prenom_employe FROM Employe ORDER BY id_employe;
Mais je voudrais y rajouter un identifiant qui m'est passé en _SESSION par PHP :
$requete = "SELECT id_employe, nom_employe, prenom_employe FROM Employe WHERE id_employe >&< '".$_SESSION['id']."' ORDER BY id_employe;";
Je ne sais pas si ca répond exactement a tes questions ...
Et moi pour ce qui est optimisation SQL ... Et sincèrement ca ne sera pas super super lourd (j'espere pas), une 100 de lignes au maximum ... dont une selection de 20 personnes a afficher en meme temps ... donc je pense pas que ca soit tres lourd !
Posté : 17 avr. 2007, 19:42
par Hubert Roksor
Ben du coup tu vas probablement utiliser le truc de l'UNION. Une dernière chose... euh c'est quoi le
>&< de ta requête ? Pour moi ça ressemble à un canard, mais ça doit avoir une autre signification pour SQL Server ?
PS: argh, j'allais oublier le LIMIT bizarre de SQL Server... j'essaie de me pencher dessus, sinon je te poste la soluce pour MySQL et tu t'occupes de ramer pour l'adapter

Posté : 17 avr. 2007, 19:54
par Hubert Roksor
Un exemple pour les SGBDR qui supportent LIMIT:
Code : Tout sélectionner
(
SELECT id_employe, nom_employe, prenom_employe
FROM Employe
WHERE id_employe < 'xxx'
ORDER BY id_employe DESC
LIMIT 10
)
UNION ALL
(
SELECT id_employe, nom_employe, prenom_employe
FROM Employe
WHERE id_employe >= 'xxx'
ORDER BY id_employe ASC
LIMIT 11
)
ORDER BY id_employe ASC
En gros, tu récupères les 10 enregistrements avant, puis les 11 enregistrement égaux ou supérieurs à celui du "milieu". Si tu n'as pas LIMIT c'est un petit peu plus dur. Tu dois pouvoir utiliser un curseur pour ne récupérer que les 10/11 premiers, à moins que SQL Server ait un équivalent de type "SELECT TOP 10" ou "FETCH 10 FROM...".
Comment les SQL Serveriens procèdent pour émuler LIMIT au fait ? (je connais pas mal de façons d'émuler LIMIT, mais je ne sais jamais quelle méthode correspond à quel SGBDR...

)
Posté : 17 avr. 2007, 19:59
par Snoops
Ben du coup tu vas probablement utiliser le truc de l'UNION. Une dernière chose... euh c'est quoi le
>&< de ta requête ? Pour moi ça ressemble à un canard, mais ça doit avoir une autre signification pour SQL Server ?
PS: argh, j'allais oublier le LIMIT bizarre de SQL Server... j'essaie de me pencher dessus, sinon je te poste la soluce pour MySQL et tu t'occupes de ramer pour l'adapter

MDRRRRR le canard c'est un truc qui n'a rien a voir avec SQL Server c'est moi qui vient de l'inventer >&< (il est ou le canard la dessus), c'était pour dire supérieur ET inférieur...
Pour le limit bizarre de SQL server ... je sais ca me saoule a chaque fois !
Code : Tout sélectionner
SELECT TOP 10 id_employe, nom_employe, prenom_employe
FROM
(
SELECT TOP 30 id_employe, nom_employe, prenom_employe
FROM employe
) as tab
Enfin ce truc bizarre que je domine pas vraiment !
Posté : 17 avr. 2007, 20:01
par Hubert Roksor
Code : Tout sélectionner
(
SELECT TOP 10 id_employe, nom_employe, prenom_employe
FROM Employe
WHERE id_employe < 'xxx'
ORDER BY id_employe DESC
)
UNION ALL
(
SELECT TOP 11 id_employe, nom_employe, prenom_employe
FROM Employe
WHERE id_employe >= 'xxx'
ORDER BY id_employe ASC
)
ORDER BY id_employe ASC
Ou peut-être en plusieurs requêtes avec ROWCOUNT:
Code : Tout sélectionner
SET ROWCOUNT 10;
SELECT * FROM (
SELECT id_employe, nom_employe, prenom_employe
FROM Employe
WHERE id_employe < 'xxx'
ORDER BY id_employe DESC
) AS tmp
ORDER BY id_employe ASC;
SET ROWCOUNT 11;
SELECT id_employe, nom_employe, prenom_employe
FROM Employe
WHERE id_employe >= 'xxx'
ORDER BY id_employe ASC;
SET ROWCOUNT 0
J'ai vu qu'il y avait un ROW_NUMBER() mais ça n'a pas l'air d'avoir le moindre avantage ici. Enfin, essaie ça et raconte-nous si ça fonctionne

Posté : 17 avr. 2007, 20:05
par Snoops
En fait la requete que je dois trouver doit certainement etre une imbrication + une association de top ... enfin une grosse galere quoa !!!
du genre :
Code : Tout sélectionner
SELECT top 7 *
FROM employe
WHERE id_employe >= (SELECT TOP 1 *
FROM (SELECT TOP 3 *
FROM employe
WHERE id_employe = _SESSION
ORDER BY id_employe DESC) AS 'toto'
ORDER BY id_employe ASC)
ORDER BY id_employe asc;
Faudra que je test ce truc bizarre demain

Posté : 17 avr. 2007, 20:11
par Snoops
Je crois qu'il y a un bug sous SQL Server avec UNION, soit un probleme de version (une version minimale obligatoire) soit que ca ne fonctionne pas ... Je m'étais déjà penché dessus a une epoque ... et j'avais abandonné alors que ca a l'air super interessant, donc j'en conclu que ca n'avait pas du fonctionner ... (Ah Microsoft ...)
Je ne connais pas "ROWCOUNT n" mais j'ai cru comprendre que ca ne selectionnait que les n premieres lignes ... ca peut etre interessant ... mais c'est en 2 requetes et dans ce cas autant faire 2 requetes avec TOP en PHP que l'on réunirait dans un tableau pour l'utiliser après ...
Et moi je voudrais essayer en une seule ... Mais c'est bien ca me fait apprendre de nouvelles choses
Je ferais tous ces tests demain au boulot sur mon server et je vous posterais mes différents retours !!!
Merci encore a toi, enfin a vous ... et a toi plus particulierement

Posté : 18 avr. 2007, 09:50
par Snoops
Bonjour,
Bon j'ai testé mon code je vous affiche les résultats puis je m'en vais testé la méthode de Hubert.
Cette requete fonction très bien :
Code : Tout sélectionner
SELECT TOP 7 *
FROM EMPLOYE
WHERE (Id_employe >= 'pellardy.d')
Celle-ci aussi :
Code : Tout sélectionner
SELECT TOP 1 * FROM (SELECT TOP 3 *
FROM EMPLOYE
WHERE (Id_employe < 'pellardy.d')
ORDER BY Id_employe DESC) DERIVEDTBL ORDER BY Id_employe ASC;
Et en combinant les 2 ... :
Code : Tout sélectionner
SELECT TOP 7 *
FROM EMPLOYE
WHERE (Id_employe >=
(SELECT TOP 1 *
FROM (SELECT TOP 3 *
FROM EMPLOYE
WHERE (Id_employe < 'pellardy.d')
ORDER BY Id_employe DESC) DERIVEDTBL
ORDER BY Id_employe))
ORDER BY Id_employe ASC;
Erreur !!!!
"Une seule expression peut être spécifiée dans la liste de sélection quand la sous-requête n'est pas introduite par EXISTS."
Bon je vous laisse plancher là dessus (parce que moi je n'y comprend rien), moi je vais tester les UNION et autres ROWCOUNT ...
Posté : 18 avr. 2007, 10:17
par Snoops
Donc voici le test avec UNION (UNION n'est pas pris en charge par Enterprise Manager ... il faut utiliser l'analyseur de requete ...)
Code : Tout sélectionner
(
SELECT TOP 10 id_employe, nom_employe, prenom_employe
FROM Employe
WHERE id_employe < 'pellardy.d'
ORDER BY id_employe DESC
)
UNION ALL
(
SELECT TOP 11 id_employe, nom_employe, prenom_employe
FROM Employe
WHERE id_employe >= 'pellardy.d'
ORDER BY id_employe ASC
)
ORDER BY id_employe ASC
La réponse est la suivante :
"Syntaxe incorrecte vers le mot clé 'ORDER'."
C'est pour les 2 ORDER des 2 requetes ...
J'ai essayé de trouver un peu de doc sur le net, alors effectivement UNION etant du SQL pur ... SQL Server est obligé de le gérer, mais tous les codes qu'ils me donnent que j'essaye d'adapter a mon cas ... rien ne passe!
J'ai bien réussi à créer une vue qui me retourne les bons résultats sauf ... pour la premiere requete (et de plus elle me met une erreur à la création). La première requete me renvoi les 10 premiers enregistrement de la table et non précédent le nom passé dans le WHERE ...
Je vais tester le ROWCOUNT ...