Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Base de données ou flou artistique?

29 réponses
Avatar
LiR
Bonjour à tous,

Je crée une requête Sélection dans Access XP SP3.
Cette requête repose sur une requête et 3 tables, liées par des jointures,
mais peu importe en fait.

1.
Je mets une condition sur un champ d'une des tables
La requête me renvoie alors zéro enregistrement

2.
J'ajoute une seconde condition sur un autre champ d'une autre table de la
requête
Cette condition est ajoutée sur la même ligne q'en 1., donc elle est liée
par AND à la première condition
La requête me renvoie plusieurs enregistrements

Ce comportement est, vous en conviendrez, tout simplement impossible
théoriquement.

Pour l'info (mais cela n'a aucun effet sur le principe) :
Condition 1 sur le champ 1 : Vrai Ou Est Null
Condition 2 sur le champ 1 : <>0

A noter, pour s'étonner encore un peu, que si je mets comme condition 2 : >0
Alors la requête, à nouveau, me retourne zéro enregistrement

Quelqu'un saurait d'où peut venir un comportement aussi catastrophique?

10 réponses

1 2 3
Avatar
Dragan
J'oubliais aussi, les option d'access permettent de fixer le nombre max de
lignes à retourner par défaut ce nombre est fixée à 1000 enregistrements.




"Dragan" a écrit :

Ok, je confirme ceux sont des constantes de définition dans tous les langages
de programmation. Dans les requêtes, il est toujours préférable d'utiliser
leur valeur.
Bon, je reconnais m'être emballé à la lecture du premier post; et ne pas
l'avoir lu correctement.
Il y a je crois quelques incohérences dans la requête; entre le RIGHT JOIN
qui est censé permettre de retourner les enregistrements de la table
DossierEtbObj quelque soit le contenu de la table apDevisStatus et la clause
WHERE qui stipule au contraire que la table apDevisStatus ne doit pas être
vide; puisque au moins un de ces champs doit répondre au critère.

En clair, la première requête telle qu'elle est construite ne peut renvoyer
que les enregistrements de apDevisStatus qui répondent au critère. Et si
cette table est vide la requête ne renvoie aucun enregitrement.






"LiR" a écrit :

> Bonjour,
>
> Je vous remercie de vous être penché sur ma question
>
> En fait, TRUE et FALSE existent tout à fait en SQL.
> Ce ne sont pas vraiment des constantes, mais plutôt des mots-clés.
> Remplacer True par -1 et False par 0 ne change rien dans mes requêtes
> (d'ailleurs ça ne change de manière générale, puisque, comme vous dites, ce
> sont les mêmes valeurs)
>
> En fait, pour un nombre, de la même manière qu'en VBA,
> Jet considèrera comme Vrai toute valeur différente de 0.
>
> La simple requête suivante permet de s'en convaincre :
>
> SELECT True As v1, 2=True As v2;
>
> Elle renvoie
> v1 : -1
> v2 : -1
>
> Mon problème est plutôt que Jet interprèete 0 à la place de NULL
> pour le champ devistatus_ok.
>
> J'ai remarqué une chose très étrange :
> Si la requête est de type Recordset dynamique, elle renvoie 0 pour
> devistatus_ok
> Si la requête est de type Instantané, elle renvoie bien NULL pour
> devistatus_ok
>
> Finalement, j'ai simplifié la condition en enlevant le True :
> Cela ne change rien, la requête suivante ne renvoie aucun enregistrement.
>
> Requête test_005 :
>
> SELECT InstrDevis.ID_INSTRDEVIS
> FROM (apDevisStatus
> RIGHT JOIN DossierEtbObj
> ON apDevisStatus.N_DEVISSTATUS = DossierEtbObj.dossetbobj_etat)
> INNER JOIN InstrDevis
> ON DossierEtbObj.ID_DOSSETBOBJ = InstrDevis.IDR_DOSSETBOBJ
> WHERE (((apDevisStatus.devisstatus_ok) Is Null));
>
>
>
> "Dragan" a écrit :
>
> > Bonjour LiR,
> > il n'y a aucun problème. Les valeurs TRUE et FALSE sont en fait des
> > constantes de programmation pour un entier long, sous VBA access TRUE = -1 et
> > FALSE = 0; ces constantes n'existent pas sous SQL. Il faut donc dans une
> > requête les remplacer par leur valeur.
> > En clair, il faut juste remplacer :
> > devisstatus_ok=true :
> > devisstatus_ok=-1 ou (devistatus_ok<>0 AND NOT devisstatus_ok IS NULL)
> > devisstatus_okúlse :
> > devistatus_ok=0 ou (devistatus_ok<>-1 AND NOT devisstatus_ok IS NULL)
> >
> >
> >
> > "LiR" a écrit :
> >
> > > Bonjour,
> > >
> > > Voici les données
> > >
> > >
> > > TABLE : apDevisStatus
> > > -------------------------
> > > C'est simple : aucun enregistrement
> > >
> > >
> > > TABLE : DossierEtbObj
> > > -------------------------
> > >
> > > 10000 enregistrements, avec :
> > > ID_DOSSETBOBJ : de 1 à 10000
> > > dossetbobj_etat : NULL partout
> > >
> > > TABLE : InstrDevis
> > > --------------------
> > >
> > > 10000 enregistrements, avec :
> > > ID_INSTRDEVIS : de 1 à 10000
> > > IDR_DOSSETBOBJ : égal à ID_INSTRDEVIS
> > >
> > >
> > > Avec ces valeurs, la requête test_003 ne retourne aucun enregistrement
> > >
> > > Ce qui est très intéressant, c'est que si je supprime les enregistrements
> > > des tables DossierEtbObj et InstrDevis au dessus de 1000,
> > > c'est-à-dire que je garde 1000 enregistrements dans chaque table,
> > > avec les ID allant de 1 à 1000, alors là, Ô miracle :
> > > La requête test_003 renvoie.... tenez vous bien.... 1000 enregistrements
> > > avec ID_INSTRDEVIS allant de 1 à 1000.
> > > On n'en attendait pas moins d'elle, elle a été concue pour cela!
> > >
> > > Alors elle peut retourner 1000 enregistrements, mais 10000 semble être trop
> > > lui demander.
> > > J'espère que vous comprenez bien désormais l'étendue du problème.
> > >
> > >
> > > Alors juste pour finir, la cerise sur le gâteau :
> > >
> > > La requête check_003 suivante :
> > >
> > > SELECT InstrDevis.ID_INSTRDEVIS, apDevisStatus.N_DEVISSTATUS,
> > > apDevisStatus.devisstatus_ok
> > > FROM (apDevisStatus RIGHT JOIN DossierEtbObj ON apDevisStatus.N_DEVISSTATUS
> > > = DossierEtbObj.dossetbobj_etat) INNER JOIN InstrDevis ON
> > > DossierEtbObj.ID_DOSSETBOBJ = InstrDevis.IDR_DOSSETBOBJ
> > >
> > > Cette requête est exactement la même que test_003
> > > mais elle ne filtre pas et elle affiche les champs pour vérification
> > > Cette requête check_003 renvoie 10000 enregistrement avec N_DEVISSTATUS à
> > > NULL partout (normal, puisqu'il n'y a AUCUN enregistrement dans la table
> > > apDevisStatus), mais devisstatus_ok à 0 (zéro) partout.
> > >
> > > Alors d'où sort ce zéro dans le champ devisstatus_ok ???
> > >
> > > Note : pour observer le résultat de la requête check_003,
> > > dans les propriétés du champ devisstatus_ok
> > > j'ai enlevé le format "oui/non" et l'affichage du contrôle "case à cocher"
> > >
> > > Donc :
> > > Sous certaines conditions, MS Jet peut comprendre qu'un booléen absent vaut
> > > NULL.
> > > Sous d'autres, il ne peut pas estimer qu'un Booléen puisse valoir autre
> > > chose que 0 ou -1.
> > >
> > > Inutile de dire qu'une solution serait de changer le type de données du
> > > champ devisstatus_ok en numérique entier (dans ce cas, effectivement,
> > > test_0003 renvoie les enregistrement, même s'il y en a 10000).
> > >
> > > Je vous remercie de votre attention,
> > >
> > > LiR
> > >
> > > "Sylvain Lafontaine" a écrit :
> > >
> > > > Premièrement, vous devriez aussi nous donner quelques exemples de lignes de
> > > > data afin que tout le monde puisse reproduire à l'identique votre problème
> > > > (le nombre minimum de lignes requises si possible et si vous êtes capable de
> > > > le faire, sous le format de requête INSERT).
> > > >
> > > > Deuxièmement, comme vous utilisez des RIGHT JOIN sous Access, il faut
> > > > peut-être pas trop chercher à comprendre. Probablement que sur SQL-Server,
> > > > vous obtiendrez le résultat désiré.
> > > >
> > > > Aussi, les RIGHT JOIN sont plus difficiles à lire et à interpréter que les
> > > > LEFT JOIN; vous devriez arrêter d'utiliser des RIGHT JOIN et utiliser
> > > > exclusivement des LEFT JOIN. Il est également possible qu'un utilisant un
> > > > Left Join à la place d'un Right Join qu'Access va vous donner le résultat
> > > > voulu. Avec JET, on ne sait jamais.
> > > >
> > > > --
> > > > Sylvain Lafontaine, ing.
> > > > MVP pour « Windows Live Platform »
> > > > Courriel: sylvain aei ca (remplissez les blancs, svp.)
> > > > Consultant indépendant et programmation à distance pour Access et
> > > > SQL-Server.
> > > >
> > > >
> > > > "LiR" wrote in message
> > > > news:
> > > > > Bonjour,
> > > > >
> > > > > Voici le contenu exhaustif des objets de ma base (3 tables et 2 requêtes)
> > > > >
> > > > > TABLE : apDevisStatus
> > > > > -------------------------
> > > > > N_DEVISSTATUS : Entier long (PRIMARY_KEY)
> > > > > devisstatus_label : Texte(32)
> > > > > devisstatus_ok : Oui/Non
> > > > >
> > > > > TABLE : DossierEtbObj
> > > > > -------------------------
> > > > > ID_DOSSETBOBJ : NuméroAuto (PRIMARY_KEY)
> > > > > dossetbobj_etat : Entier long
> > > > >
> > > > > TABLE : InstrDevis
> > > > > --------------------
> > > > > ID_INSTRDEVIS : Entier long (PRIMARY_KEY)
> > > > > IDR_DOSSETBOBJ : Entier long
> > > > > devs_date : Date/Heure
> > > > >
> > > > > REQUÊTE : test_0003
> > > > > ------------------------
> > > > > SELECT InstrDevis.ID_INSTRDEVIS
> > > > > FROM (apDevisStatus RIGHT JOIN DossierEtbObj ON
> > > > > apDevisStatus.N_DEVISSTATUS = DossierEtbObj.dossetbobj_etat) INNER JOIN
> > > > > InstrDevis ON DossierEtbObj.ID_DOSSETBOBJ = InstrDevis.IDR_DOSSETBOBJ
> > > > > WHERE (((apDevisStatus.devisstatus_ok)=True Or
> > > > > (apDevisStatus.devisstatus_ok) Is Null));
> > > > >
> > > > > REQUÊTE : test_0004
> > > > > ------------------------
> > > > > SELECT InstrDevis.ID_INSTRDEVIS
> > > > > FROM (apDevisStatus RIGHT JOIN DossierEtbObj ON
> > > > > apDevisStatus.N_DEVISSTATUS = DossierEtbObj.dossetbobj_etat) INNER JOIN
> > > > > InstrDevis ON DossierEtbObj.ID_DOSSETBOBJ = InstrDevis.IDR_DOSSETBOBJ
> > > > > WHERE (((apDevisStatus.devisstatus_ok)=True Or
> > > > > (apDevisStatus.devisstatus_ok) Is Null) AND ((InstrDevis.ID_INSTRDEVIS) Is
> > > > > Not Null));
> > > > >
> > > > >
> > > > > Il n'y a absolument rien d'autre dans ma base en dehors de ces 3 tables et
> > > > > ces 2 requêtes
> > > > > Ni autre table (sauf les tables système, évidemment), ni autre requête, ni
> > > > > formulaire, ni état, bi module VBA, ni page de données, ni macro... rien.
> > > > >
> > > > > La requête test_003 ne retourne aucun enregistrement
> > > > > La requête test_003 ne retourne plusieurs enregistrements
> > > > >
> > > > > Comme vous pouvez le voir, la seule différence entre les 2 requêtes est
> > > > > que test_004 a une condition de plus dans la clause WHERE
> > > > > Cette condition est : AND ((InstrDevis.ID_INSTRDEVIS) Is Not Null))
> > > > >
> > > > > Le fait est que, mathématiquement, il est impossible que la requête
> > > > > test_004 retourne plus de résultats que test_003
> > > > > Pour la simple et bonne raison que mathématiquement (A AND B AND C) peut
> > > > > être VRAI uniquement si (A AND B) est VRAI!
> > > > >
> > > > > Si vous reproduisez ma base à partir du modèle ci-dessus, elle
> > > > > fonctionnera, fort heureusement correctement.
> > > > > Le problème constaté concerne ma base, qui semble être endommagée...
> > > > >
> > > > > Seulement j'ai vérifié les index, clés primaires, contraintes....
> > > > > J'ai compacté, importé, recompacté...
> > > > > Rien à faire.
> > > > > Je n'arrive pas à mettre la main sur le petit grain de sel qui fait
> > > > > dérailler ma base.
> > > > > A moins que ce soit un immense rocher (comme toujours, plus c'est gros...)
> > > > >
> > > > >
> > > > > "Sylvain Lafontaine" a écrit dans le
> > > > > message de news:
> > > > >> Peut-être que si vous nous montreriez votre requête SQL - avec si
> > > > >> possible le détail pertinent des tables et des données - on pourrait tous
> > > > >> ensemble regarder cela et trouver où se trouve votre erreur et réduire
> > > > >> votre étonnement à un niveau plus acceptable.
> > > > >>
> > > > >> --
> > > > >> Sylvain Lafontaine, ing.
> > > > >> MVP pour « Windows Live Platform »
> > > > >> Courriel: sylvain aei ca (remplissez les blancs, svp.)
> > > > >> Consultant indépendant et programmation à distance pour Access et
> > > > >> SQL-Server.
> > > > >>
> > > > >>
> > > > >> "LiR" wrote in message
> > > > >> news:
> > > > >>> Bonjour à tous,
> > > > >>>
> > > > >>> Je crée une requête Sélection dans Access XP SP3.
> > > > >>> Cette requête repose sur une requête et 3 tables, liées par des
> > > > >>> jointures, mais peu importe en fait.
> > > > >>>
> > > > >>> 1.
> > > > >>> Je mets une condition sur un champ d'une des tables
> > > > >>> La requête me renvoie alors zéro enregistrement
> > > > >>>
> > > > >>> 2.
> > > > >>> J'ajoute une seconde condition sur un autre champ d'une autre table de
> > > > >>> la requête
> > > > >>> Cette condition est ajoutée sur la même ligne q'en 1., donc elle est
> > > > >>> liée par AND à la première condition
> > > > >>> La requête me renvoie plusieurs enregistrements
> > > > >>>
> > > > >>> Ce comportement est, vous en conviendrez, tout simplement impossible
> > > > >>> théoriquement.
> > > > >>>
> > > > >>> Pour l'info (mais cela n'a aucun effet sur le principe) :
> > > > >>> Condition 1 sur le champ 1 : Vrai Ou Est Null
> > > > >>> Condition 2 sur le champ 1 : <>0
> > > > >>>
> > > > >>> A noter, pour s'étonner encore un peu, que si je mets comme condition 2
> > > > >>> : >0


Avatar
LiR
Bonjour,

Comme je l'ai indiqué, la requête fonctionne parfaitement s'il y a 1000
enregistrements dans chaque table DossierEtbObj et InstrDevis.
Elle renvoie alors N enregistrements, N étant le nombre d'enregistrements
dans les tables DossierEtbObj et InstrDevis.
Les tests montrent qu'à partir du moment où les tables DossierEtbObj et
InstrDevis contiennent au moins 3072 enregistrements, la requête ne retourne
plus aucun enregistrement.

La première chose à conclure est que cette requête fonctionne.
La seconde est qu'elle craque si on lui donne trop d'enregistrements.

La limitation de 1000 enregistrements concerne les listes de valeurs pour le
filtrage par formulaire et n'a donc rien à voir avec les requêtes.

La construction de la requête n'est pas à remettre en cause.
Pour rassurer certains, je vous confirme qu'une construction avec un LEFT
JOIN donne exactement les mêmes résultats.


La requête en question est, pour rappel, sous sa forme la plus simple :

Requête test_005 :

SELECT InstrDevis.ID_INSTRDEVIS
FROM (apDevisStatus
RIGHT JOIN DossierEtbObj
ON apDevisStatus.N_DEVISSTATUS = DossierEtbObj.dossetbobj_etat)
INNER JOIN InstrDevis
ON DossierEtbObj.ID_DOSSETBOBJ = InstrDevis.IDR_DOSSETBOBJ
WHERE (((apDevisStatus.devisstatus_ok) Is Null));



"Dragan" a écrit :

J'oubliais aussi, les option d'access permettent de fixer le nombre max de
lignes à retourner par défaut ce nombre est fixée à 1000 enregistrements.




"Dragan" a écrit :

> Ok, je confirme ceux sont des constantes de définition dans tous les langages
> de programmation. Dans les requêtes, il est toujours préférable d'utiliser
> leur valeur.
> Bon, je reconnais m'être emballé à la lecture du premier post; et ne pas
> l'avoir lu correctement.
> Il y a je crois quelques incohérences dans la requête; entre le RIGHT JOIN
> qui est censé permettre de retourner les enregistrements de la table
> DossierEtbObj quelque soit le contenu de la table apDevisStatus et la clause
> WHERE qui stipule au contraire que la table apDevisStatus ne doit pas être
> vide; puisque au moins un de ces champs doit répondre au critère.
>
> En clair, la première requête telle qu'elle est construite ne peut renvoyer
> que les enregistrements de apDevisStatus qui répondent au critère. Et si
> cette table est vide la requête ne renvoie aucun enregitrement.
>
>
>
>
>
>
> "LiR" a écrit :
>
> > Bonjour,
> >
> > Je vous remercie de vous être penché sur ma question
> >
> > En fait, TRUE et FALSE existent tout à fait en SQL.
> > Ce ne sont pas vraiment des constantes, mais plutôt des mots-clés.
> > Remplacer True par -1 et False par 0 ne change rien dans mes requêtes
> > (d'ailleurs ça ne change de manière générale, puisque, comme vous dites, ce
> > sont les mêmes valeurs)
> >
> > En fait, pour un nombre, de la même manière qu'en VBA,
> > Jet considèrera comme Vrai toute valeur différente de 0.
> >
> > La simple requête suivante permet de s'en convaincre :
> >
> > SELECT True As v1, 2=True As v2;
> >
> > Elle renvoie
> > v1 : -1
> > v2 : -1
> >
> > Mon problème est plutôt que Jet interprèete 0 à la place de NULL
> > pour le champ devistatus_ok.
> >
> > J'ai remarqué une chose très étrange :
> > Si la requête est de type Recordset dynamique, elle renvoie 0 pour
> > devistatus_ok
> > Si la requête est de type Instantané, elle renvoie bien NULL pour
> > devistatus_ok
> >
> > Finalement, j'ai simplifié la condition en enlevant le True :
> > Cela ne change rien, la requête suivante ne renvoie aucun enregistrement.
> >
> > Requête test_005 :
> >
> > SELECT InstrDevis.ID_INSTRDEVIS
> > FROM (apDevisStatus
> > RIGHT JOIN DossierEtbObj
> > ON apDevisStatus.N_DEVISSTATUS = DossierEtbObj.dossetbobj_etat)
> > INNER JOIN InstrDevis
> > ON DossierEtbObj.ID_DOSSETBOBJ = InstrDevis.IDR_DOSSETBOBJ
> > WHERE (((apDevisStatus.devisstatus_ok) Is Null));
> >
> >
> >
> > "Dragan" a écrit :
> >
> > > Bonjour LiR,
> > > il n'y a aucun problème. Les valeurs TRUE et FALSE sont en fait des
> > > constantes de programmation pour un entier long, sous VBA access TRUE = -1 et
> > > FALSE = 0; ces constantes n'existent pas sous SQL. Il faut donc dans une
> > > requête les remplacer par leur valeur.
> > > En clair, il faut juste remplacer :
> > > devisstatus_ok=true :
> > > devisstatus_ok=-1 ou (devistatus_ok<>0 AND NOT devisstatus_ok IS NULL)
> > > devisstatus_okúlse :
> > > devistatus_ok=0 ou (devistatus_ok<>-1 AND NOT devisstatus_ok IS NULL)
> > >
> > >
> > >
> > > "LiR" a écrit :
> > >
> > > > Bonjour,
> > > >
> > > > Voici les données
> > > >
> > > >
> > > > TABLE : apDevisStatus
> > > > -------------------------
> > > > C'est simple : aucun enregistrement
> > > >
> > > >
> > > > TABLE : DossierEtbObj
> > > > -------------------------
> > > >
> > > > 10000 enregistrements, avec :
> > > > ID_DOSSETBOBJ : de 1 à 10000
> > > > dossetbobj_etat : NULL partout
> > > >
> > > > TABLE : InstrDevis
> > > > --------------------
> > > >
> > > > 10000 enregistrements, avec :
> > > > ID_INSTRDEVIS : de 1 à 10000
> > > > IDR_DOSSETBOBJ : égal à ID_INSTRDEVIS
> > > >
> > > >
> > > > Avec ces valeurs, la requête test_003 ne retourne aucun enregistrement
> > > >
> > > > Ce qui est très intéressant, c'est que si je supprime les enregistrements
> > > > des tables DossierEtbObj et InstrDevis au dessus de 1000,
> > > > c'est-à-dire que je garde 1000 enregistrements dans chaque table,
> > > > avec les ID allant de 1 à 1000, alors là, Ô miracle :
> > > > La requête test_003 renvoie.... tenez vous bien.... 1000 enregistrements
> > > > avec ID_INSTRDEVIS allant de 1 à 1000.
> > > > On n'en attendait pas moins d'elle, elle a été concue pour cela!
> > > >
> > > > Alors elle peut retourner 1000 enregistrements, mais 10000 semble être trop
> > > > lui demander.
> > > > J'espère que vous comprenez bien désormais l'étendue du problème.
> > > >
> > > >
> > > > Alors juste pour finir, la cerise sur le gâteau :
> > > >
> > > > La requête check_003 suivante :
> > > >
> > > > SELECT InstrDevis.ID_INSTRDEVIS, apDevisStatus.N_DEVISSTATUS,
> > > > apDevisStatus.devisstatus_ok
> > > > FROM (apDevisStatus RIGHT JOIN DossierEtbObj ON apDevisStatus.N_DEVISSTATUS
> > > > = DossierEtbObj.dossetbobj_etat) INNER JOIN InstrDevis ON
> > > > DossierEtbObj.ID_DOSSETBOBJ = InstrDevis.IDR_DOSSETBOBJ
> > > >
> > > > Cette requête est exactement la même que test_003
> > > > mais elle ne filtre pas et elle affiche les champs pour vérification
> > > > Cette requête check_003 renvoie 10000 enregistrement avec N_DEVISSTATUS à
> > > > NULL partout (normal, puisqu'il n'y a AUCUN enregistrement dans la table
> > > > apDevisStatus), mais devisstatus_ok à 0 (zéro) partout.
> > > >
> > > > Alors d'où sort ce zéro dans le champ devisstatus_ok ???
> > > >
> > > > Note : pour observer le résultat de la requête check_003,
> > > > dans les propriétés du champ devisstatus_ok
> > > > j'ai enlevé le format "oui/non" et l'affichage du contrôle "case à cocher"
> > > >
> > > > Donc :
> > > > Sous certaines conditions, MS Jet peut comprendre qu'un booléen absent vaut
> > > > NULL.
> > > > Sous d'autres, il ne peut pas estimer qu'un Booléen puisse valoir autre
> > > > chose que 0 ou -1.
> > > >
> > > > Inutile de dire qu'une solution serait de changer le type de données du
> > > > champ devisstatus_ok en numérique entier (dans ce cas, effectivement,
> > > > test_0003 renvoie les enregistrement, même s'il y en a 10000).
> > > >
> > > > Je vous remercie de votre attention,
> > > >
> > > > LiR
> > > >
> > > > "Sylvain Lafontaine" a écrit :
> > > >
> > > > > Premièrement, vous devriez aussi nous donner quelques exemples de lignes de
> > > > > data afin que tout le monde puisse reproduire à l'identique votre problème
> > > > > (le nombre minimum de lignes requises si possible et si vous êtes capable de
> > > > > le faire, sous le format de requête INSERT).
> > > > >
> > > > > Deuxièmement, comme vous utilisez des RIGHT JOIN sous Access, il faut
> > > > > peut-être pas trop chercher à comprendre. Probablement que sur SQL-Server,
> > > > > vous obtiendrez le résultat désiré.
> > > > >
> > > > > Aussi, les RIGHT JOIN sont plus difficiles à lire et à interpréter que les
> > > > > LEFT JOIN; vous devriez arrêter d'utiliser des RIGHT JOIN et utiliser
> > > > > exclusivement des LEFT JOIN. Il est également possible qu'un utilisant un
> > > > > Left Join à la place d'un Right Join qu'Access va vous donner le résultat
> > > > > voulu. Avec JET, on ne sait jamais.
> > > > >
> > > > > --
> > > > > Sylvain Lafontaine, ing.
> > > > > MVP pour « Windows Live Platform »
> > > > > Courriel: sylvain aei ca (remplissez les blancs, svp.)
> > > > > Consultant indépendant et programmation à distance pour Access et
> > > > > SQL-Server.
> > > > >
> > > > >
> > > > > "LiR" wrote in message
> > > > > news:
> > > > > > Bonjour,
> > > > > >
> > > > > > Voici le contenu exhaustif des objets de ma base (3 tables et 2 requêtes)
> > > > > >
> > > > > > TABLE : apDevisStatus
> > > > > > -------------------------
> > > > > > N_DEVISSTATUS : Entier long (PRIMARY_KEY)
> > > > > > devisstatus_label : Texte(32)
> > > > > > devisstatus_ok : Oui/Non
> > > > > >
> > > > > > TABLE : DossierEtbObj
> > > > > > -------------------------
> > > > > > ID_DOSSETBOBJ : NuméroAuto (PRIMARY_KEY)
> > > > > > dossetbobj_etat : Entier long
> > > > > >
> > > > > > TABLE : InstrDevis
> > > > > > --------------------
> > > > > > ID_INSTRDEVIS : Entier long (PRIMARY_KEY)
> > > > > > IDR_DOSSETBOBJ : Entier long
> > > > > > devs_date : Date/Heure
> > > > > >
> > > > > > REQUÊTE : test_0003
> > > > > > ------------------------
> > > > > > SELECT InstrDevis.ID_INSTRDEVIS
> > > > > > FROM (apDevisStatus RIGHT JOIN DossierEtbObj ON
> > > > > > apDevisStatus.N_DEVISSTATUS = DossierEtbObj.dossetbobj_etat) INNER JOIN
> > > > > > InstrDevis ON DossierEtbObj.ID_DOSSETBOBJ = InstrDevis.IDR_DOSSETBOBJ
> > > > > > WHERE (((apDevisStatus.devisstatus_ok)=True Or
> > > > > > (apDevisStatus.devisstatus_ok) Is Null));
> > > > > >
> > > > > > REQUÊTE : test_0004
> > > > > > ------------------------
> > > > > > SELECT InstrDevis.ID_INSTRDEVIS
> > > > > > FROM (apDevisStatus RIGHT JOIN DossierEtbObj ON
> > > > > > apDevisStatus.N_DEVISSTATUS = DossierEtbObj.dossetbobj_etat) INNER JOIN
> > > > > > InstrDevis ON DossierEtbObj.ID_DOSSETBOBJ = InstrDevis.IDR_DOSSETBOBJ
> > > > > > WHERE (((apDevisStatus.devisstatus_ok)=True Or
> > > > > > (apDevisStatus.devisstatus_ok) Is Null) AND ((InstrDevis.ID_INSTRDEVIS) Is
> > > > > > Not Null));
> > > > > >
> > > > > >
> > > > > > Il n'y a absolument rien d'autre dans ma base en dehors de ces 3 tables et
> > > > > > ces 2 requêtes
> > > > > > Ni autre table (sauf les tables système, évidemment), ni autre requête, ni
> > > > > > formulaire, ni état, bi module VBA, ni page de données, ni macro... rien.
> > > > > >
> > > > > > La requête test_003 ne retourne aucun enregistrement
> > > > > > La requête test_003 ne retourne plusieurs enregistrements
> > > > > >
> > > > > > Comme vous pouvez le voir, la seule différence entre les 2 requêtes est
> > > > > > que test_004 a une condition de plus dans la clause WHERE
> > > > > > Cette condition est : AND ((InstrDevis.ID_INSTRDEVIS) Is Not Null))
> > > > > >
> > > > > > Le fait est que, mathématiquement, il est impossible que la requête
> > > > > > test_004 retourne plus de résultats que test_003
> > > > > > Pour la simple et bonne raison que mathématiquement (A AND B AND C) peut
> > > > > > être VRAI uniquement si (A AND B) est VRAI!
> > > > > >
> > > > > > Si vous reproduisez ma base à partir du modèle ci-dessus, elle
> > > > > > fonctionnera, fort heureusement correctement.
> > > > > > Le problème constaté concerne ma base, qui semble être endommagée...
> > > > > >
> > > > > > Seulement j'ai vérifié les index, clés primaires, contraintes....
> > > > > > J'ai compacté, importé, recompacté...
> > > > > > Rien à faire.
> > > > > > Je n'arrive pas à mettre la main sur le petit grain de sel qui fait
> > > > > > dérailler ma base.
> > > > > > A moins que ce soit un immense rocher (comme toujours, plus c'est gros...)
> > > > > >
> > > > > >
> > > > > > "Sylvain Lafontaine" a écrit dans le
> > > > > > message de news:
> > > > > >> Peut-être que si vous nous montreriez votre requête SQL - avec si
> > > > > >> possible le détail pertinent des tables et des données - on pourrait tous
> > > > > >> ensemble regarder cela et trouver où se trouve votre erreur et réduire
> > > > > >> votre étonnement à un niveau plus acceptable.
> > > > > >>
> > > > > >> --
> > > > > >> Sylvain Lafontaine, ing.
> > > > > >> MVP pour « Windows Live Platform »
> > > > > >> Courriel: sylvain aei ca (remplissez les blancs, svp.)
> > > > > >> Consultant indépendant et programmation à distance pour Access et
> > > > > >> SQL-Server.
> > > > > >>
> > > > > >>
> > > > > >> "LiR" wrote in message
> > > > > >> news:
> > > > > >>> Bonjour à tous,
> > > > > >>>
> > > > > >>> Je crée une requête Sélection dans Access XP SP3.
> > > > > >>> Cette requête repose sur une requête et 3 tables, liées par des
> > > > > >>> jointures, mais peu importe en fait.
> > > > > >>>
> > > > > >>> 1.
> > > > > >>> Je mets une condition sur un champ d'une des tables
> > > > > >>> La requête me renvoie alors zéro enregistrement
> > > > > >>>
> > > > > >>> 2.
> > > > > >>> J'ajoute une seconde condition sur un autre champ d'une autre table de
> > > > > >>> la requête
> > > > > >>> Cette condition est ajoutée sur la même ligne q'en 1., donc elle est
> > > > > >>> liée par AND à la première condition
> > > > > >>> La requête me renvoie plusieurs enregistrements
> > > > > >>>
> > > > > >>> Ce comportement est, vous en conviendrez, tout simplement impossible


Avatar
Dragan
LiR, au départ tu indiques un problème mais la construction de la première
requête n'est pas cohérente.
Ici, tu as retiré le test True sur devisstatus_ok. Maintenant que dit ta
requête :
tu sélectionnes l'ensemble des enresgistrements commun à DossieretbObj et
InstrDevis qu'il aient un équivalent ou non dans apDevisStatuts et parmi ces
enregistrements tu sélectionnes ceux pour lesquels un champ apDevisStatus a
une certaine valeur. Quelle cohérence y a-t-il entre ne pas tenir compte de
la présence d'enregistrements dans une table et exiger de cette même table
des enregistrements correspondant à un critère ?
Soit la clause WHERE ne doit pas faire mention de apDevisStatus soit tu
changes le RIGHT JOIN en INNER JOIN.

Maintenant tu ne testes que la nullité du champ or si la table
apDevisStatus est vide, tous les enregistrements de DossierEtbObj sont
retournés et la clause WHERE ne présente aucun intéret.

La clause FROM fait de apDevisStatus la table la moins importante
La clause WHERE indique le constraire.

La limitation de 1000 enregistrements concerne les listes de valeurs pour le
filtrage par formulaire et n'a donc rien à voir avec les requêtes.


Tu as raison, j'ai dit n'importe quoi. Un peu fatigué hier soir.
Avatar
Michel__D
Bonjour,

As-tu définit les relations entre les tables ?

PS:Chez moi en ayant défini les relations, il n'y a aucun problème.
Avatar
LiR
Bonjour,

Vous dites :
"tous les enregistrements de DossierEtbObj sont
retournés et la clause WHERE ne présente aucun intéret"

Premièrement :
Je m'évertue précisément à expliquer depuis le début que la requête
ne renvoie pas d'enregistrement.
Vous convenez donc qu'il y a un problème non?

Deuxièmement :
Que la requête ait un intérêt ou non, ecxusez-moi, n'est pas le propos.
Cette requête est, en gros, ce qu'on appelle une requête de
non-correspondance.
Pourquoi je l'ai faite n'est pas le sujet.
Sachez qu'évidemment ma requête d'origine était bien plus complète et comlexe,
mais ne croyez-vous pas que cette requête très simple est largement
suffisante comme sujet d'étude?

La problématique n'est pas de savoir à quoi sert cette requête.
La problématique n'est pas de savoir si elle est bien construite.

Cette requête est construite comme elle l'est.
La question est : pourquoi lorsque les tables comptent plus de 3172
enregistrements elle cesse de fonctionner?

"Dragan" a écrit :

LiR, au départ tu indiques un problème mais la construction de la première
requête n'est pas cohérente.
Ici, tu as retiré le test True sur devisstatus_ok. Maintenant que dit ta
requête :
tu sélectionnes l'ensemble des enresgistrements commun à DossieretbObj et
InstrDevis qu'il aient un équivalent ou non dans apDevisStatuts et parmi ces
enregistrements tu sélectionnes ceux pour lesquels un champ apDevisStatus a
une certaine valeur. Quelle cohérence y a-t-il entre ne pas tenir compte de
la présence d'enregistrements dans une table et exiger de cette même table
des enregistrements correspondant à un critère ?
Soit la clause WHERE ne doit pas faire mention de apDevisStatus soit tu
changes le RIGHT JOIN en INNER JOIN.

Maintenant tu ne testes que la nullité du champ or si la table
apDevisStatus est vide, tous les enregistrements de DossierEtbObj sont
retournés et la clause WHERE ne présente aucun intéret.

La clause FROM fait de apDevisStatus la table la moins importante
La clause WHERE indique le constraire.

> La limitation de 1000 enregistrements concerne les listes de valeurs pour le
> filtrage par formulaire et n'a donc rien à voir avec les requêtes.
Tu as raison, j'ai dit n'importe quoi. Un peu fatigué hier soir.




Avatar
LiR
Bonjour,

Vous avez tout-à-fait raison.

Effectivement, j'avais fait des tests aussi à ce niveau :

Si les relations existent, la requête retourne bien les enregistrements.
Si les relations n'existent pas, la requête ne retourne pas d'enregistrement.

Le phénomène a également lieu avec la présence ou non de clés primaires.

En gros, nous voici en présence d'un requête, qui, selon la présence de
relations, d'index et le nombre d'enregistrements dans les tables n'a pas le
même fonctionnement.

Les ralations, les index et le nombre d'enregistrements influent sur la
rapidité d'accès aux données et la possibilité ou non de les modifier.

En aucun cas cela ne doit avoir de rapport avec le fonctionnement d'une
requête SQL.

Personnellement j'appelle ça un dysfonctionnement.

En fait, je ne cherche pas à faire une requête qui fonctionne,
je cherche à connaître l'explication de ce comportement lunatique


"Michel__D" a écrit :

Bonjour,

As-tu définit les relations entre les tables ?

PS:Chez moi en ayant défini les relations, il n'y a aucun problème.




Avatar
Dragan
LiR a écrit :
"Premièrement :
Je m'évertue précisément à expliquer depuis le début que la requête
ne renvoie pas d'enregistrement.
Vous convenez donc qu'il y a un problème non?"


Vous venez de dire le contraire :
"Elle renvoie alors N enregistrements, N étant le nombre d'enregistrements
dans les tables DossierEtbObj et InstrDevis."



La critique que je fais sur la requête vient de votre conclusion. Aucune
conclusion ne peut être tirée de la requête telle qu'elle est consrtuite.
Pour voir s'il y a un problème ou non, il faudrait décomposer la requête.
Ex:
SELECT id_dossetbobj,devisstatus_ok
FROM DossierEtbObj LEFT JOIN apDevisStatus
ON DossierEtObj.Dossetbobj_etat=apDevisStatus.n_devisstatus
à tester dans un premier temps quand DossieretbObj contient 1000 et 3172
enregistrements.
Avatar
Michel__D
Re,

"LiR" a écrit dans le message de news:
Bonjour,

Vous avez tout-à-fait raison.

Effectivement, j'avais fait des tests aussi à ce niveau :

Si les relations existent, la requête retourne bien les enregistrements.
Si les relations n'existent pas, la requête ne retourne pas d'enregistrement.

Le phénomène a également lieu avec la présence ou non de clés primaires.

En gros, nous voici en présence d'un requête, qui, selon la présence de
relations, d'index et le nombre d'enregistrements dans les tables n'a pas le
même fonctionnement.

Les ralations, les index et le nombre d'enregistrements influent sur la
rapidité d'accès aux données et la possibilité ou non de les modifier.

En aucun cas cela ne doit avoir de rapport avec le fonctionnement d'une
requête SQL.

Personnellement j'appelle ça un dysfonctionnement.

En fait, je ne cherche pas à faire une requête qui fonctionne,
je cherche à connaître l'explication de ce comportement lunatique




Ben c'est comme quand tu construis un immeuble au départ tu pourrais
trés bien faire sans prévoir de renfort et puis te rend vite compte que tu
es obligé de prévoir des renforts sinon tout s'écroule.

De plus utiliser une requête avec des jointures implique des relations et
donc il y a quelque part une incohérence à ne pas définir les relations.
Avatar
LiR
Pour ma part une jointure dans une requête n'implique ni ne nécessite aucune
relation.
L'incohérence c'est une requête qui ne fait pas son boulot.

Il suffit de lire ceci pour s'en convaincre :
http://office.microsoft.com/fr-fr/access/HA102051321036.aspx#3

Et la définition des LEFT et RIGHT JOIN, fort justement,
ne fait aucune mention de relation
http://office.microsoft.com/fr-fr/access/HA012314891036.aspx?pid=CH100728991036

Excusez-moi, mais que celui qui n'a jamais fait une jointure dans une requête
entre 2 tables qui n'ont pas de relation lève le doigt!

Je me répête, je suis désolé, mais pour moi une requête incohérente ça
n'existe pas.
Un moteur de données digne de ce nom doit pouvoir répondre à une requête
dans la limite
de ses spécifications de fonctionnement (au passage, le moteur ne va pas
philospher sur l'utilité ou non de votre requête !)
Vous avez raison, Microsoft Access nécessite visiblement quelques renforts.
J'aimerais juste connaître sa limite de fonctionnement.

Je rappelle que si le champ apdevisstatus_ok est de type entier long,
qu'il y ait clé primaire ou on, relations ou non, 1 ou 100000
enregistrements, la requête fonctionne.
Cela vous paraît-il incohérent qu'une requête fonctionne sans index ni
relation?
Moi non.

"Michel__D" a écrit :

Re,

"LiR" a écrit dans le message de news:
> Bonjour,
>
> Vous avez tout-à-fait raison.
>
> Effectivement, j'avais fait des tests aussi à ce niveau :
>
> Si les relations existent, la requête retourne bien les enregistrements.
> Si les relations n'existent pas, la requête ne retourne pas d'enregistrement.
>
> Le phénomène a également lieu avec la présence ou non de clés primaires.
>
> En gros, nous voici en présence d'un requête, qui, selon la présence de
> relations, d'index et le nombre d'enregistrements dans les tables n'a pas le
> même fonctionnement.
>
> Les ralations, les index et le nombre d'enregistrements influent sur la
> rapidité d'accès aux données et la possibilité ou non de les modifier.
>
> En aucun cas cela ne doit avoir de rapport avec le fonctionnement d'une
> requête SQL.
>
> Personnellement j'appelle ça un dysfonctionnement.
>
> En fait, je ne cherche pas à faire une requête qui fonctionne,
> je cherche à connaître l'explication de ce comportement lunatique


Ben c'est comme quand tu construis un immeuble au départ tu pourrais
trés bien faire sans prévoir de renfort et puis te rend vite compte que tu
es obligé de prévoir des renforts sinon tout s'écroule.

De plus utiliser une requête avec des jointures implique des relations et
donc il y a quelque part une incohérence à ne pas définir les relations.




Avatar
Michel__D
"LiR" a écrit dans le message de news:
Pour ma part une jointure dans une requête n'implique ni ne nécessite aucune
relation.
L'incohérence c'est une requête qui ne fait pas son boulot.

Il suffit de lire ceci pour s'en convaincre :
http://office.microsoft.com/fr-fr/access/HA102051321036.aspx#3

Et la définition des LEFT et RIGHT JOIN, fort justement,
ne fait aucune mention de relation :
http://office.microsoft.com/fr-fr/access/HA012314891036.aspx?pid=CH100728991036

Excusez-moi, mais que celui qui n'a jamais fait une jointure dans une requête
entre 2 tables qui n'ont pas de relation lève le doigt!

Je me répête, je suis désolé, mais pour moi une requête incohérente ça
n'existe pas.
Un moteur de données digne de ce nom doit pouvoir répondre à une requête
dans la limite
de ses spécifications de fonctionnement (au passage, le moteur ne va pas
philospher sur l'utilité ou non de votre requête !)
Vous avez raison, Microsoft Access nécessite visiblement quelques renforts.
J'aimerais juste connaître sa limite de fonctionnement.

Je rappelle que si le champ apdevisstatus_ok est de type entier long,
qu'il y ait clé primaire ou on, relations ou non, 1 ou 100000
enregistrements, la requête fonctionne.
Cela vous paraît-il incohérent qu'une requête fonctionne sans index ni
relation?
Moi non.



Pour moi c'est incohérent d'utiliser un mécanisme qui met en oeuvre des
relations (jointures) et de ne pas définir ces mêmes relations et lorsque
ces relations ne sont pas définis, et bien Access le signale par un
résultat erroné, c'est sur cela serait mieux qu'il t'informe gentiment que
tu as omis de définir quelque chose, maintenant c'est un logiciel de
base de données relationnelles, donc ...
1 2 3