faire une selection 10 lignes avant et apres une valeur

Répondre


Cette question est un moyen d’empêcher des soumissions automatisées de formulaires par des robots.
Smileys
:D :) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :!: :?: :idea: :arrow: :| :mrgreen: =D> #-o =P~ :^o :non: :priere: 8-|
Voir plus de smileys
  Revue du sujet
 

  Étendre la vue Revue du sujet : faire une selection 10 lignes avant et apres une valeur

par Snoops » 18 avr. 2007, 10:21

Bon bah voilà ...

Avec ce code :

Code : Tout sélectionner

SET ROWCOUNT 10; SELECT * FROM ( SELECT id_employe, nom_employe, prenom_employe FROM Employe WHERE id_employe < 'pellardy.d' 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 >= 'pellardy.d' ORDER BY id_employe ASC; SET ROWCOUNT 0
L'erreur est la suivante (pour le premier ORDER BY) :
"La clause ORDER BY n'est pas valide dans les vues, les fonctions Inline, les tables dérivées et les sous-requêtes, sauf si TOP est également spécifié."

Bon bah soit quelqu'un a une idée ... soit je vais devoir le faire en 2 requetes ... snif :cry:

par Snoops » 18 avr. 2007, 10:17

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 ...

par Snoops » 18 avr. 2007, 09:50

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 ...

par Snoops » 17 avr. 2007, 20:11

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 :D

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 :wink:

par Snoops » 17 avr. 2007, 20:05

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 :P

par Hubert Roksor » 17 avr. 2007, 20:01

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 ;)

par Snoops » 17 avr. 2007, 19:59

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 ? :lol:

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... :lol:

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 !

par Hubert Roksor » 17 avr. 2007, 19:54

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... :roll:)

par Hubert Roksor » 17 avr. 2007, 19:42

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 ? :lol:

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 :)

par Snoops » 17 avr. 2007, 19:36

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 !

par Hubert Roksor » 17 avr. 2007, 19:28

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.

par Snoops » 17 avr. 2007, 19:13

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é.

par Hubert Roksor » 17 avr. 2007, 19:10

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.

par Snoops » 17 avr. 2007, 19:08

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.

par Hubert Roksor » 17 avr. 2007, 19:07

Difficile à dire comme ça, comment sont classés les résultats ?