IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage SQL Discussion :

Résultats différents pour 2 requêtes a priori identiques


Sujet :

Langage SQL

  1. #1
    J1
    J1 est déconnecté
    Membre averti Avatar de J1
    Inscrit en
    Mai 2004
    Messages
    321
    Détails du profil
    Informations forums :
    Inscription : Mai 2004
    Messages : 321
    Points : 335
    Points
    335
    Par défaut Résultats différents pour 2 requêtes a priori identiques
    Bonjour,

    voilà mon souci. Le résultat d'une de mes requêtes SQL me semble étrange et j'ai fini par isoler la cause du problème : un filtre modifie le résultat de ma requête de façon inattendue. Pour illustrer la question, voici ma requête :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
    SELECT LTE.tblEpreuve_txtNomFr, LPECPMA.tblPerformance_sngPerformance, M.tblMembre_txtLogin 
    FROM
    (
     (
      SELECT *, [?1_Saisir_le_numero_de_membre] AS Param_NumMembre
      FROM rqtListerToutesEpreuves
     )
     AS LTE
     LEFT JOIN rqtListerPerformancesEtCalculerPositionsMembresActifs AS LPECPMA
     ON LPECPMA.tblPerformance_blnRespectRegles_tblRespectRegles=LTE.tblRespectRegles_blnRespectRegles
     AND LPECPMA.tblPerformance_octOrdre_tblEpreuve=LTE.tblEpreuve_octOrdre
     AND LPECPMA.tblMembre_lngNumAuto=LTE.Param_NumMembre
    )
    LEFT JOIN 
    (
     SELECT M1.tblMembre_txtLogin, M1.tblMembre_lngNumAuto
     FROM tblMembre AS M1 
     WHERE M1.tblMembre_txtLogin=M1.tblMembre_txtLogin /*FILTRE BIDON*/
    )
    AS M
    ON M.tblMembre_lngNumAuto=LPECPMA.tblMembre_lngNumAuto;
    J'ai introduit la 4e ligne en partant de la fin pour mettre en évidence mon problème. En effet, ce filtre, alors qu'il devrait n'avoir aucune conséquence, modifie le résultat de ma requête.
    En l'occurrence, avec ce filtre, ma requête me renvoie 136 enregistrements ; sans ce filtre, elle m'en renvoie 24.
    Concrètement, puisque ma requête est une requête LEFT JOIN, elle devrait toujours retourner 24 enregistrements, puisque c'est le nombre d'enregistrements de rqtListerToutesEpreuves (LTE).
    Pour info, 136 correspond au nombre d'enregistrements de rqtListerPerformancesEtCalculerPositionsMembresActifs (LPECPMA).

    J'en déduis donc que le filtre WHERE M1.tblMembre_txtLogin=M1.tblMembre_txtLogin fait planter ma jointure LEFT JOIN. Si je le remplace par tout autre filtre bidon basé sur un champ de tblMembre (M1) comme WHERE M1.tblMembre_lngNumAuto=M1.tblMembre_lngNumAuto, le problème persiste (136 enregistrements renvoyés).
    En revanche, si je le remplace par WHERE 1=1, ma requête me renvoie 24 enregistrements comme prévu.

    D'où ma question : quelqu'un voit-il en quoi ce filtre peut influencer le résultat de ma requête ?

    PS : désolé pour la longueur des noms de champs.
    PPS : je sais que la requête ne semble pas "pertinente", c'est dû au fait que j'ai volontairement modifié ma requête d'origine afin de mettre en évidence mon problème.
    PPPS : je travaille sous Access 2000.

    Merci d'avance pour vos lumières.

  2. #2
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 772
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 772
    Points : 52 732
    Points
    52 732
    Billets dans le blog
    5
    Par défaut
    Votre syntaxe à base de parenthèses imbriquées est particulièrement délirante. Votre requête devrait être écrite de la sorte :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    SELECT LTE.tblEpreuve_txtNomFr, LPECPMA.tblPerformance_sngPerformance, M.tblMembre_txtLogin
    FROM   rqtListerToutesEpreuves AS LTE
           LEFT OUTER JOIN rqtListerPerformancesEtCalculerPositionsMembresActifs AS LPECPMA
                ON     LPECPMA.tblPerformance_blnRespectRegles_tblRespectRegles
                         = LTE.tblRespectRegles_blnRespectRegles
                     AND LPECPMA.tblPerformance_octOrdre_tblEpreuve
                         = LTE.tblEpreuve_octOrdre
                     AND LPECPMA.tblMembre_lngNumAuto
                         = LTE.Param_NumMembre
           LEFT OUTER JOIN tblMembre AS M1
                ON M1.tblMembre_lngNumAuto=LPECPMA.tblMembre_lngNumAuto
    WHERE  M1.tblMembre_txtLogin=M1.tblMembre_txtLogin
    Dès lors il est normal qu'avec ou sans le WHERE le résultat diffère. En effet si pour certaines lignes, la colonne tblMembre_txtLogin n'est pas renseignée (marqueur NULL) alors la comparaison vaut UNKNOWN et n'est donc pas prise en compte.
    En revanche en l'absence de cette clause WHERE toutes les lignes sont prise en compte même celles dont la colonne tblMembre_txtLogin n'est pas renseignée.
    Si vous voulez le prouver, il suffit de rajouter le prédicat suivant à la clause WHERE :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    OR M1.tblMembre_txtLogin IS NULL
    ou encore de porter cette clause WHERE dans le prédicat de jointure entre les tables d'alias M1 et LPECPMA, par exemple comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    SELECT LTE.tblEpreuve_txtNomFr, LPECPMA.tblPerformance_sngPerformance, M.tblMembre_txtLogin
    FROM   rqtListerToutesEpreuves AS LTE
           LEFT OUTER JOIN rqtListerPerformancesEtCalculerPositionsMembresActifs AS LPECPMA
                ON     LPECPMA.tblPerformance_blnRespectRegles_tblRespectRegles
                         = LTE.tblRespectRegles_blnRespectRegles
                     AND LPECPMA.tblPerformance_octOrdre_tblEpreuve
                         = LTE.tblEpreuve_octOrdre
                     AND LPECPMA.tblMembre_lngNumAuto
                         = LTE.Param_NumMembre
           LEFT OUTER JOIN tblMembre AS M1
                ON M1.tblMembre_lngNumAuto=LPECPMA.tblMembre_lngNumAuto
                   AND M1.tblMembre_txtLogin=M1.tblMembre_txtLogin
    Le mieux que je puisse vous conseiller, c'est d'apprendre le langage SQL... Mon site SQLpro comme mes bouquins peuvent vous y aider !

    Enfin, sachez que le niveau de SQL d'Access n'est même pas au niveau de la norme de 1992 (SQL est un langage fortement normalisé). Or nous en sommes à la norme 2003 après avoir passer l'importante norme SQL:1999 (relationnel objet). De plus le format de base de données Access et le moteur relationnel associé (jet) est d'une pérénité plutôt incertaine...
    Passez donc à MSDE ou SQL Server Express qui sont des version light et gratuite du moteur de MS SQL Server 2000 et 2005.

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  3. #3
    J1
    J1 est déconnecté
    Membre averti Avatar de J1
    Inscrit en
    Mai 2004
    Messages
    321
    Détails du profil
    Informations forums :
    Inscription : Mai 2004
    Messages : 321
    Points : 335
    Points
    335
    Par défaut
    Tout d'abord, je vous remercie d'avoir pris le temps de me répondre et vous félicite pour votre site, que j'ai déjà eu l'occasion de consulter.

    Comme je l'avais précisé dans mon message, ma requête ne se veut pas pertinente, mais elle est syntaxiquement correcte et sert à illustrer ma question. Mon but n'est pas de la réécrire (je l'ai déjà fait, obtenant une requête proche de la deuxième que vous proposez), mais de comprendre pourquoi, en l'état, elle ne fonctionne pas comme prévu.

    Concernant les requêtes que vous proposez, la première ne correspond pas à ma problèmatique. Le filtre WHERE M1.tblMembre_txtLogin=M1.tblMembre_txtLogin, que vous appliquez une fois les jointures réalisées, n'a fort logiquement pas les mêmes conséquences que dans la requête que j'avais écrite.
    Comme je le disais plus haut, votre deuxième requête constitue en revanche une alternative à la mienne (à ceci près que vous avez supprimé le paramètre [?1_Saisir_le_numero_de_membre] que j'avais introduit dans LTE). Mais je le répète, l'objet de mon message n'était pas de remplacer ma requête par une autre mais de comprendre POURQUOI elle ne fonctionne pas.

    Ce qui m'amène à votre remarque sur le filtre WHERE M1.tblMembre_txtLogin=M1.tblMembre_txtLogin, filtre qui n'est pas aussi "transparent" que je le pensais, et qui était donc mal choisi pour illustrer mon propos.
    Je précise donc que, si je remplace le filtre WHERE M1.tblMembre_txtLogin=M1.tblMembre_txtLogin par WHERE tblMembre_txtLogin Is Null OR tblMembre_txtLogin Is Not Null, le problème reste le même (136 enregistrements renvoyés avec le filtre, 24 sans le filtre).
    Ma question reste donc entière.

    Concernant votre remarque sur Access, je dois dire que... je fais avec ce que j'ai !
    J'avais déjà envisagé d'installer SQL Server 2005 Express Edition, mais il requiert le Framework .Net. En revanche, je ne connaissais pas MSDE, qui a l'air moins gourmand. Merci pour le renseignement.

    Citation Envoyé par SQLpro
    Votre syntaxe à base de parenthèses imbriquées est particulièrement délirante.
    J'utilise les parenthèses à 3 reprises :
    - 2 fois pour délimiter des sous-requêtes, auxquelles j'assigne ensuite un alias.
    - 1 fois pour délimiter le résultat de ma première jointure, pour ainsi réaliser une nouvelle jointure entre ce résultat et une autre sous-requête. Sauf erreur de ma part, ce parenthèsage est indispensable pour enchaîner 2 jointures sous Access (peut-être la norme SQL ne l'impose-t-elle pas).

  4. #4
    Expert éminent

    Avatar de Maxence HUBICHE
    Homme Profil pro
    Développeur SQLServer/Access
    Inscrit en
    Juin 2002
    Messages
    3 842
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Développeur SQLServer/Access

    Informations forums :
    Inscription : Juin 2002
    Messages : 3 842
    Points : 9 197
    Points
    9 197
    Par défaut
    J'aimerai juste signaler que cette syntaxe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    SELECT LTE.NomFR, LPCEPMA.Performance, M1.Login
     
    FROM (
    LTE LEFT JOIN LPCEPMA ON 
            LTE.NumMembre = LPCEPMA.NumMembre 
    AND LTE.octOrdre = LPCEPMA.octOrdre 
    AND LTE.respectRegles = LPCEPMA.respectRegles) 
    LEFT JOIN M1 ON 
            LPCEPMA.Login = M1.Login 
    AND LPCEPMA.NumAuto = M1.NumAuto
     
    WHERE M1.Login Like '%coucou%';
    Est PARFAITEMENT supportée par Access.
    il faut juste savoir aller faire un clic dans :
    Outils / Options / Requêtes
    sur la case à cocher de la rubrique Syntaxe SQL Compatible ANSI (SQL92)
    En voici la preuve :

    Donc, maintenant, si on pouvait éviter de raconter n'importe quoi comme :
    Access, c'est nul !
    Access, seuls les non pros travaillent avec !
    Access n'est pas compatible ANSI92
    les ADP passent pasr ODBC pour accéder à SQLServer
    Access est mort (ceci est FAUX, archi FAUX ! C'est du dénigrement, ca peut aller chercher loin...)
    ...
    alors, et seulement alors, je pense qu'on pourrait juger de la pertinence des 'pros' qui en parlent...

  5. #5
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 772
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 772
    Points : 52 732
    Points
    52 732
    Billets dans le blog
    5
    Par défaut
    Maxence, ce n'est pas parce que Access te met une belle fenêtre avec Compatibilité SQL ANSI 92 que cela est vrai !. Même sous MS SQL Server certains points de la norme ne sont pas respectés, par exemple le comportement des contraintes d'unicité de SQL Server ne respecte pas le niveau minimal de SQL 1992. D'autant plus que la norme dont tu parle est franchement obsolète. Entre temps il y a eu deux nouvelles normes :
    SQL:1999 en 1999
    SQL:2003 en 2003

    Pour te montrer à quel point MS Access est loin d'être normatif (je n'ai pas le temps de tout tester), prenons par exemple CREATE TABLE qui ne prend pas en compte les contraintes CHECK
    Démo :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    CREATE TABLE T_TEST_CONTRAINTES_TCT
    (COL1    INTEGER CONSTRAINT CK_TCT_COL1 CHECK (COL1 BETWEEN 0 AND 100))
    Or c'est dans le niveau "entry level" de la norme SQL2 (1992). Tous les SGBDR le font, y comprit Paradox, une base de données fichiers datant de 1986 !!!

    Je note cepandant que quelques points ont été améliorés, comme les joker du like...

    A lire : http://www.dbazine.com/db2/db2-disarticles/gulutzan3

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  6. #6
    Expert éminent

    Avatar de Maxence HUBICHE
    Homme Profil pro
    Développeur SQLServer/Access
    Inscrit en
    Juin 2002
    Messages
    3 842
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Développeur SQLServer/Access

    Informations forums :
    Inscription : Juin 2002
    Messages : 3 842
    Points : 9 197
    Points
    9 197
    Par défaut
    A ce moment là, il faut que tu aies l'honneteté de reconnaître que

    * AUCUN SGBDR n'est FULL Compatible avec une norme 1999 ou même 2003, car
    * TOUS les éditeurs partent de la norme pour faire ce qu'ils veulent (Aussi bien Oracle, que Microsoft, que qui que tu choisisse - cf ton propre lien)

    et, donc, arrêter de tirer à boulets rouges sur Access comme tu le fais dès que tu as 30 secondes, surtout que j'ai rebondi sur une aberration que TU as dite :
    Citation Envoyé par SQLpro
    Enfin, sachez que le niveau de SQL d'Access n'est même pas au niveau de la norme de 1992
    Ce qui est donc FAUX... tout simplement.
    Oui, il n'implémente pas complètement la norme.
    Mais il est au niveau de la norme.
    Tes autres critiques portaient sur les parenthèses inclusives obligatoires, sur le non respect de la norme, etc.
    Et ces paroles, non constructives, ne sont rien d'autre que du dénigrement, ce qui est très grave sur le plan juridique.

    Mais bon, d'un autre côté, comme je l'ai montré, le % peuvent remplacer les * (les fameux jokers dont tu parles) et le SQL peut être compatible avec la norme SQL92 (même si elle ne suit pas la norme complète) au lieu d'être le simple SQL Access, car il suffit de savoir le demander.

Discussions similaires

  1. Réponses: 3
    Dernier message: 04/05/2011, 15h27
  2. [ZF 1.8] Résultats différents pour mêmes actions
    Par diagonale dans le forum MVC
    Réponses: 7
    Dernier message: 08/08/2009, 23h12
  3. [MySQL] Résultat bizarre pour une requête
    Par masseur dans le forum PHP & Base de données
    Réponses: 2
    Dernier message: 09/05/2007, 11h46
  4. gettime 2 résultats différents pour une meme date
    Par krolineeee dans le forum Collection et Stream
    Réponses: 5
    Dernier message: 05/03/2007, 14h36
  5. Résultats différent entre une requête SQL, et la même en VBA
    Par thetaps dans le forum Requêtes et SQL.
    Réponses: 3
    Dernier message: 23/09/2005, 12h05

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo