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

[WD7.5 206h] Phénomène SQL

10 réponses
Avatar
mat
Bonjour,

Est-ce que quelqu'un trouve une explication pour les difficultés avec la
requête N° 3 qui est en principe identique à la 4 mais renvoie n'importe
quoi? La base est toujours le FROM et WHERE du No 1, le reste
rajouté suivant les filtres en place. Donc, la seule chose
différente entre les 4 versions c'est le WHERE à partir de la 2e ligne.

J'aimerais bien comprendre ce problème. Merci de vos lumières.

Mat


1) OK, retourne 240 enreg.:
FROM Contract LEFT OUTER JOIN ContractDetail on Contract.IDContract =
ContractDetail.IDContract,
ContractDetail LEFT OUTER JOIN Product on ContractDetail.IDProduct =
Product.IDProduct, Contract LEFT OUTER JOIN Address on
Contract.IDCustSupp = Address.IDAddress

WHERE Contract.IDContractType < 8
AND ContractDetail.Balance <> 0


2) OK, retourne 1 enreg.:
FROM Contract LEFT OUTER JOIN ContractDetail on Contract.IDContract =
ContractDetail.IDContract,
ContractDetail LEFT OUTER JOIN Product on ContractDetail.IDProduct =
Product.IDProduct, Contract LEFT OUTER JOIN Address on
Contract.IDCustSupp = Address.IDAddress

WHERE Contract.IDContractType < 8
AND Contract.IDContractType IN (2,4)
AND Contract.Date >= '20030101'
AND Contract.Date <= '20031231'
AND ContractDetail.Balance <> 0


3) Retourne > 93000 enregistrements (le fichier ContractDetail a env
4000 enreg, donc les lignes sont multipliées pour une raison X):
FROM Contract LEFT OUTER JOIN ContractDetail on Contract.IDContract =
ContractDetail.IDContract,
ContractDetail LEFT OUTER JOIN Product on ContractDetail.IDProduct =
Product.IDProduct, Contract LEFT OUTER JOIN Address on
Contract.IDCustSupp = Address.IDAddress

WHERE Contract.IDContractType < 8
AND Contract.IDContractType IN (2,4)
AND ContractDetail.Balance <> 0


4) OK, retourne 160 enregs (correspond à ce que je voulais obtenir avec 3):
FROM Contract LEFT OUTER JOIN ContractDetail on Contract.IDContract =
ContractDetail.IDContract,
ContractDetail LEFT OUTER JOIN Product on ContractDetail.IDProduct =
Product.IDProduct, Contract LEFT OUTER JOIN Address on
Contract.IDCustSupp = Address.IDAddress

WHERE Contract.IDContractType < 8
AND Contract.IDContract IN (SELECT IDContract FROM Contract C WHERE
IDContractType IN (2,4) )
AND ContractDetail.Balance <> 0

10 réponses

Avatar
mat
J'ai oublié: il s'agit bien de SQL sur HF.
Avatar
Roumegou
mat avait prétendu :
Bonjour,

Est-ce que quelqu'un trouve une explication pour les difficultés avec la
requête N° 3 qui est en principe identique à la 4 mais renvoie n'importe
quoi? La base est toujours le FROM et WHERE du No 1, le reste
rajouté suivant les filtres en place. Donc, la seule chose
différente entre les 4 versions c'est le WHERE à partir de la 2e ligne.

J'aimerais bien comprendre ce problème. Merci de vos lumières.

Mat


1) OK, retourne 240 enreg.:
FROM Contract LEFT OUTER JOIN ContractDetail on Contract.IDContract > ContractDetail.IDContract,
ContractDetail LEFT OUTER JOIN Product on ContractDetail.IDProduct > Product.IDProduct, Contract LEFT OUTER JOIN Address on
Contract.IDCustSupp = Address.IDAddress

WHERE Contract.IDContractType < 8
AND ContractDetail.Balance <> 0



1ere question Pourquoi un left join entre contractDetail et contract ?
Il me semble difficile pour un contractdetail d'exister sans un
Contract.
Meme chose entre ContractDetail et Product.
Attention à la jointure gauche qui plombe les performances d'une
requête.

pour moi ce serait plutôt (en mySQL car je ne pratique pas le HF mais
j'espère que ce n'est pas différent)
FROM (((ContractDetail INNER JOIN Contract on
ContractDetail.IDContract=Contract.IDContract) INNER JOIN Product
on ContractDetail.IDProduct = Product.IDProduct) LEFT JOIN Adress ON
Contract.IDCustSupp = Address.IDAddress)
WHERE ...



2) OK, retourne 1 enreg.:
FROM Contract LEFT OUTER JOIN ContractDetail on Contract.IDContract > ContractDetail.IDContract,
ContractDetail LEFT OUTER JOIN Product on ContractDetail.IDProduct > Product.IDProduct, Contract LEFT OUTER JOIN Address on
Contract.IDCustSupp = Address.IDAddress

WHERE Contract.IDContractType < 8
AND Contract.IDContractType IN (2,4)
AND Contract.Date >= '20030101'
AND Contract.Date <= '20031231'
AND ContractDetail.Balance <> 0



Si tu nous changes les Where, on veut bien te croire que cela ne donne
pas le meme nbre d'enregs?



3) Retourne > 93000 enregistrements (le fichier ContractDetail a env 4000
enreg, donc les lignes sont multipliées pour une raison X):
FROM Contract LEFT OUTER JOIN ContractDetail on Contract.IDContract > ContractDetail.IDContract,
ContractDetail LEFT OUTER JOIN Product on ContractDetail.IDProduct > Product.IDProduct, Contract LEFT OUTER JOIN Address on
Contract.IDCustSupp = Address.IDAddress

WHERE Contract.IDContractType < 8
AND Contract.IDContractType IN (2,4)
AND ContractDetail.Balance <> 0



Parce que tu utilises des jointures gauche alors qu'il faut utiliser
des équijointures



4) OK, retourne 160 enregs (correspond à ce que je voulais obtenir avec 3):
FROM Contract LEFT OUTER JOIN ContractDetail on Contract.IDContract > ContractDetail.IDContract,
ContractDetail LEFT OUTER JOIN Product on ContractDetail.IDProduct > Product.IDProduct, Contract LEFT OUTER JOIN Address on
Contract.IDCustSupp = Address.IDAddress

WHERE Contract.IDContractType < 8
AND Contract.IDContract IN (SELECT IDContract FROM Contract C WHERE
IDContractType IN (2,4) )
AND ContractDetail.Balance <> 0




A mon avis soit tu as un modèle spec ;-) soit tu n'as pas bien compris
la notion de left join.

ContractDetail INNER JOIN Contract on
ContractDetail.IDContract=Contract.IDContract : je prends tous les
détail contrats et leur en-tête contrat (le plus logique non ?)

Contract LEFT OUTER JOIN ContractDetail on Contract.IDContract =
ContractDetail.IDContract : je prends tous les contrats meme ceux qui
n'ont pas de détails (pourquoi pas ?)

ContractDetail LEFT OUTER JOIN Contract on
ContractDetail.IDContract=Contract.IDContract : je prends tous les
détails contrats meme s'il n'ont pas d'en tete (bizarre ?)


Volià, j'espère que cela pourra t'aider.

--
Eric Roumegou
http://cerbermail.com/?TSoulBerPA
(cliquez sur le lien ci-dessus pour me contacter en privé)
Avatar
mat
Roumegou wrote:
1) OK, retourne 240 enreg.:
FROM Contract LEFT OUTER JOIN ContractDetail on Contract.IDContract >> ContractDetail.IDContract,
ContractDetail LEFT OUTER JOIN Product on ContractDetail.IDProduct >> Product.IDProduct, Contract LEFT OUTER JOIN Address on
Contract.IDCustSupp = Address.IDAddress

WHERE Contract.IDContractType < 8
AND ContractDetail.Balance <> 0




1ere question Pourquoi un left join entre contractDetail et contract ?
Il me semble difficile pour un contractdetail d'exister sans un Contract.
Meme chose entre ContractDetail et Product.
Attention à la jointure gauche qui plombe les performances d'une requête.



Le left outer join est entre Contract et ContractDetail, ne pas
vice-versa. Je pense LEFT se réfère au fichier qui est a gauche (de
LEFT), ou je me trompe? Le but de cette jointure est que je veux
récupérer des entêtes sans détails.

Je suis d'accord que le code n'est peut-être pas très nette. Dans mon
expérience, de temps en temps un serveur se bloque ce qui résulte dans
des enregistrements incomplets. Je veux que la requête me retourne
toutes commandes, même sans code client, enregistrement détail et code
produit.

pour moi ce serait plutôt (en mySQL car je ne pratique pas le HF mais
j'espère que ce n'est pas différent)
FROM (((ContractDetail INNER JOIN Contract on
ContractDetail.IDContract=Contract.IDContract) INNER JOIN Product
on ContractDetail.IDProduct = Product.IDProduct) LEFT JOIN Adress ON
Contract.IDCustSupp = Address.IDAddress)
WHERE ...



Il me semble que celle-ci ne me retourne pas les entêtes sans détails...

2) OK, retourne 1 enreg.:
FROM Contract LEFT OUTER JOIN ContractDetail on Contract.IDContract >> ContractDetail.IDContract,
ContractDetail LEFT OUTER JOIN Product on ContractDetail.IDProduct >> Product.IDProduct, Contract LEFT OUTER JOIN Address on
Contract.IDCustSupp = Address.IDAddress

WHERE Contract.IDContractType < 8
AND Contract.IDContractType IN (2,4)
AND Contract.Date >= '20030101'
AND Contract.Date <= '20031231'
AND ContractDetail.Balance <> 0




Si tu nous changes les Where, on veut bien te croire que cela ne donne
pas le meme nbre d'enregs?



J'ai spécifié que mon problème est le N° 3 par rapport au 4. Cette
exemple N° 2 montre que le IN (même que N° 3) fonctionne dans ce format,
lorsqu'il y a une autre condition.


3) Retourne > 93000 enregistrements (le fichier ContractDetail a env
4000 enreg, donc les lignes sont multipliées pour une raison X):
FROM Contract LEFT OUTER JOIN ContractDetail on Contract.IDContract >> ContractDetail.IDContract,
ContractDetail LEFT OUTER JOIN Product on ContractDetail.IDProduct >> Product.IDProduct, Contract LEFT OUTER JOIN Address on
Contract.IDCustSupp = Address.IDAddress

WHERE Contract.IDContractType < 8
AND Contract.IDContractType IN (2,4)
AND ContractDetail.Balance <> 0




Parce que tu utilises des jointures gauche alors qu'il faut utiliser des
équijointures



Je regrette, je ne comprends pas la différence au N° 2.


4) OK, retourne 160 enregs (correspond à ce que je voulais obtenir
avec 3):
FROM Contract LEFT OUTER JOIN ContractDetail on Contract.IDContract >> ContractDetail.IDContract,
ContractDetail LEFT OUTER JOIN Product on ContractDetail.IDProduct >> Product.IDProduct, Contract LEFT OUTER JOIN Address on
Contract.IDCustSupp = Address.IDAddress

WHERE Contract.IDContractType < 8
AND Contract.IDContract IN (SELECT IDContract FROM Contract C WHERE
IDContractType IN (2,4) )
AND ContractDetail.Balance <> 0





A mon avis soit tu as un modèle spec ;-) soit tu n'as pas bien compris
la notion de left join.

ContractDetail INNER JOIN Contract on
ContractDetail.IDContract=Contract.IDContract : je prends tous les
détail contrats et leur en-tête contrat (le plus logique non ?)



commentaire sous 1.


Contract LEFT OUTER JOIN ContractDetail on Contract.IDContract =
ContractDetail.IDContract : je prends tous les contrats meme ceux qui
n'ont pas de détails (pourquoi pas ?)



commentaires sous 1.


ContractDetail LEFT OUTER JOIN Contract on
ContractDetail.IDContract=Contract.IDContract : je prends tous les
détails contrats meme s'il n'ont pas d'en tete (bizarre ?)



Je ne trouve pas ceci dans mon code. Le seul ContractDetail LEFT OUTER
JOIN que je vois est celui avec Product (l'ID se trouve dans
ContractDetail).


Volià, j'espère que cela pourra t'aider.


Merci beaucoup pour ton aide. Je pense j'y arrivera si tu peux
m'expliquer pourquoi les mêmes jointures fonctionnent dans l'exemple 2
et 4, mais pas dans le No 3. Ne nombre d'enregistrements est uniquement
en cause entre les Nos 3 et 4 qui devraient, à mon avis, donner le même
résultat.

Mat
Avatar
mat
Roumegou wrote:
Volià, j'espère que cela pourra t'aider.




En HF, ton code correspond à

"FROM ContractDetail INNER JOIN Contract on
ContractDetail.IDContract=Contract.IDContract, "+...
"ContractDetail INNER JOIN Product on ContractDetail.IDProduct =
Product.IDProduct, "+...
"Contract LEFT JOIN Address ON Contract.IDCustSupp = Address.IDAddress "+...
"WHERE Contract.IDContractType < 8 "

Elle marche mais ne donne pas les entêtes sans détails.


J'ai oublié de dire que je n'ai jamais réussi d'obtenir le résultat
voulu avec les jointures indiquées. Je pense le problème vient des
filtres sur ContractDetail. Je dépanne avec une requête UNION sans aucun
filtre sur ContractDetail. Ca marche mais n'est probablement pas très
efficace.
Avatar
Roumegou
mat a utilisé son clavier pour écrire :
Roumegou wrote:
1) OK, retourne 240 enreg.:
FROM Contract LEFT OUTER JOIN ContractDetail on Contract.IDContract >>> ContractDetail.IDContract,
ContractDetail LEFT OUTER JOIN Product on ContractDetail.IDProduct >>> Product.IDProduct, Contract LEFT OUTER JOIN Address on
Contract.IDCustSupp = Address.IDAddress

WHERE Contract.IDContractType < 8
AND ContractDetail.Balance <> 0




1ere question Pourquoi un left join entre contractDetail et contract ?
Il me semble difficile pour un contractdetail d'exister sans un Contract.
Meme chose entre ContractDetail et Product.
Attention à la jointure gauche qui plombe les performances d'une requête.



Le left outer join est entre Contract et ContractDetail, ne pas vice-versa.
Je pense LEFT se réfère au fichier qui est a gauche (de LEFT), ou je me
trompe? Le but de cette jointure est que je veux récupérer des entêtes sans
détails.

Je suis d'accord que le code n'est peut-être pas très nette. Dans mon
expérience, de temps en temps un serveur se bloque ce qui résulte dans des
enregistrements incomplets. Je veux que la requête me retourne toutes
commandes, même sans code client, enregistrement détail et code produit.



Oui mais normalement une commande ne peut exister sans détail et une
ligne ne peut exister sans code produit.
Enfin, on fait comme on veut;(et cela dépend de ton analyse) mais par
expérience, des en-têtes vides provoquent des incohérences. Donc dès
que l'on supprime toutes les lignes d'une commande, on supprime
automatiquement l'en tete, ou si l'on valide une commande sans avoir
saisit de détail, on supprime l'en tete.




pour moi ce serait plutôt (en mySQL car je ne pratique pas le HF mais
j'espère que ce n'est pas différent)
FROM (((ContractDetail INNER JOIN Contract on
ContractDetail.IDContract=Contract.IDContract) INNER JOIN Product
on ContractDetail.IDProduct = Product.IDProduct) LEFT JOIN Adress ON
Contract.IDCustSupp = Address.IDAddress)
WHERE ...



Il me semble que celle-ci ne me retourne pas les entêtes sans détails...

2) OK, retourne 1 enreg.:
FROM Contract LEFT OUTER JOIN ContractDetail on Contract.IDContract >>> ContractDetail.IDContract,
ContractDetail LEFT OUTER JOIN Product on ContractDetail.IDProduct >>> Product.IDProduct, Contract LEFT OUTER JOIN Address on
Contract.IDCustSupp = Address.IDAddress







Récapitulons ce que tu veux faire dans ta requête :
Tu prends tous les contrats qui ont des lignes de contrats (autant de
fois qu'ils ont des lignes) + les contrats sans lignes,toutes les
lignes de contrats avec ou sans produits, les contrats avec ou sans
adresse.


WHERE Contract.IDContractType < 8
AND Contract.IDContractType IN (2,4)
AND Contract.Date >= '20030101'
AND Contract.Date <= '20031231'
AND ContractDetail.Balance <> 0







avec ContractDetail.Balance<>0 ; ce test élimine (pour un sgbd
normalement constitué) tous les contrats sans contractdétail puisque on
ne peut faire de tests sur une valeur null. Ou alors il faudrait
utiliser l'équivalent sql hf de coalesce ou nvl.
Donc la jointure left est discutable; l'équijointure serait plus
logique.



Si tu nous changes les Where, on veut bien te croire que cela ne donne pas
le meme nbre d'enregs?



J'ai spécifié que mon problème est le N° 3 par rapport au 4. Cette exemple N°
2 montre que le IN (même que N° 3) fonctionne dans ce format, lorsqu'il y a
une autre condition.


3) Retourne > 93000 enregistrements (le fichier ContractDetail a env 4000
enreg, donc les lignes sont multipliées pour une raison X):
FROM Contract LEFT OUTER JOIN ContractDetail on Contract.IDContract >>> ContractDetail.IDContract,
ContractDetail LEFT OUTER JOIN Product on ContractDetail.IDProduct >>> Product.IDProduct, Contract LEFT OUTER JOIN Address on
Contract.IDCustSupp = Address.IDAddress

WHERE Contract.IDContractType < 8
AND Contract.IDContractType IN (2,4)
AND ContractDetail.Balance <> 0







Ah 930000 enregistrements ?? donc HF n'est pas normalement constitué
???. La valeur null ne peut être testé donc pour
contractDetail.balance<>0, la valeur null ne satisfait pas ce test.
Il doit faire un produit scalaire. Dans tes 93000 enreg, regardes les
valeurs de IdContract, je pense qu'il y en a à null.

Mais je suis désolé, je n'arrive pas à suivre ta logique.
Tu veux toutes les lignes de contrats, avec les infos du contrats, le
produit correspondant à ligne du contrat et le contrat peut ne pas
avoir de code client (idAdress).
C'est cela ou je me trompe ???
Donc il faut partir du détail et de non de l'en tete.
Alors à la mode HF (sous toute réserve)

select ..
FROM ContractDetail INNER JOIN Contract on
ContractDetail.IdContract=Contract.IdContract,
ContractDetail INNER JOIN Product on
ContractDetail.IdProduct=Product.IdProduct,
Contract LEFT JOIN Address on Contract.IDCustSupp = Address.IDAddress
WHERE Contract.IDContractType < 8
AND Contract.IDContractType IN (2,4)
AND ContractDetail.Balance <> 0






Parce que tu utilises des jointures gauche alors qu'il faut utiliser des
équijointures



Je regrette, je ne comprends pas la différence au N° 2.


4) OK, retourne 160 enregs (correspond à ce que je voulais obtenir avec
3):
FROM Contract LEFT OUTER JOIN ContractDetail on Contract.IDContract >>> ContractDetail.IDContract,
ContractDetail LEFT OUTER JOIN Product on ContractDetail.IDProduct >>> Product.IDProduct, Contract LEFT OUTER JOIN Address on
Contract.IDCustSupp = Address.IDAddress

WHERE Contract.IDContractType < 8
AND Contract.IDContract IN (SELECT IDContract FROM Contract C WHERE
IDContractType IN (2,4) )
AND ContractDetail.Balance <> 0







Là ton IN (SELECT IDContract doit refaire une restriction sur tes 93000
enreg mais le mal a déja été fait




A mon avis soit tu as un modèle spec ;-) soit tu n'as pas bien compris la
notion de left join.

ContractDetail INNER JOIN Contract on
ContractDetail.IDContract=Contract.IDContract : je prends tous les détail
contrats et leur en-tête contrat (le plus logique non ?)



commentaire sous 1.


Contract LEFT OUTER JOIN ContractDetail on Contract.IDContract =
ContractDetail.IDContract : je prends tous les contrats meme ceux qui n'ont
pas de détails (pourquoi pas ?)



commentaires sous 1.


ContractDetail LEFT OUTER JOIN Contract on
ContractDetail.IDContract=Contract.IDContract : je prends tous les détails
contrats meme s'il n'ont pas d'en tete (bizarre ?)



Je ne trouve pas ceci dans mon code. Le seul ContractDetail LEFT OUTER JOIN
que je vois est celui avec Product (l'ID se trouve dans ContractDetail).


Volià, j'espère que cela pourra t'aider.


Merci beaucoup pour ton aide. Je pense j'y arrivera si tu peux m'expliquer
pourquoi les mêmes jointures fonctionnent dans l'exemple 2 et 4, mais pas
dans le No 3. Ne nombre d'enregistrements est uniquement en cause entre les
Nos 3 et 4 qui devraient, à mon avis, donner le même résultat.

Mat



--
Eric Roumegou
http://cerbermail.com/?TSoulBerPA
(cliquez sur le lien ci-dessus pour me contacter en privé)
Avatar
Roumegou
mat avait écrit le 24/04/2004 :
Roumegou wrote:
Volià, j'espère que cela pourra t'aider.




En HF, ton code correspond à

"FROM ContractDetail INNER JOIN Contract on
ContractDetail.IDContract=Contract.IDContract, "+...
"ContractDetail INNER JOIN Product on ContractDetail.IDProduct =
Product.IDProduct, "+...
"Contract LEFT JOIN Address ON Contract.IDCustSupp = Address.IDAddress "+...
"WHERE Contract.IDContractType < 8 "

Elle marche mais ne donne pas les entêtes sans détails.



cf mon post précédent.
Si tu fais des tests sur des zones de contractdetail (balance par ex),
il ne seront pas satisfaits pour les tuples sans contractdetail (valeur
null).
Attention, peut être cela se passe comme cela avec HF mais si tu passes
sur Oracle par ex, cela ne marchera pas. Autant prendre tout de suite
les bonnes habitudes.



J'ai oublié de dire que je n'ai jamais réussi d'obtenir le résultat voulu
avec les jointures indiquées. Je pense le problème vient des filtres sur
ContractDetail. Je dépanne avec une requête UNION sans aucun filtre sur
ContractDetail. Ca marche mais n'est probablement pas très efficace.



--
Eric Roumegou
http://cerbermail.com/?TSoulBerPA
(cliquez sur le lien ci-dessus pour me contacter en privé)
Avatar
mat
Bonsoir Eric,

Il semble très difficile de me comprendre, des fois ça m'arrive aussi
:-) Pourtant ce que je cherche est assez simple. Essayons encore une fois...

Roumegou wrote:
Oui mais normalement une commande ne peut exister sans détail et une
ligne ne peut exister sans code produit.
Enfin, on fait comme on veut;(et cela dépend de ton analyse) mais par
expérience, des en-têtes vides provoquent des incohérences. Donc dès que
l'on supprime toutes les lignes d'une commande, on supprime
automatiquement l'en tete, ou si l'on valide une commande sans avoir
saisit de détail, on supprime l'en tete.



Entre autres, je travaille avec des pays où l'électricité et les
techniciens système ne sont pas toujours les plus stables... D'abord je
crée et sauve l'entête avec son ID. Avant la saisie du premier détail je
sauve le reste de l'entête. Entretemps, lors d'une chute de courant, on
risque de rester avec une entête sans ID client. Ensuite je crée et
sauve le détail avec son ID et le reste des données du détail au passage
à un autre détail ou retour à l'entête. Entretemps, lors d'une chute de
courant, on peut rester avec un détail sans ID produit.

Si on a une chute de courant avant la création/sauvegarde du premier
détail on reste bien avec une entête sans détails....

La suppression d'une entête supprime automatiquement les détails
(gestion d'intégrité de Windev).


avec ContractDetail.Balance<>0 ; ce test élimine (pour un sgbd
normalement constitué) tous les contrats sans contractdétail puisque on
ne peut faire de tests sur une valeur null. Ou alors il faudrait



ContractDetail.Balance<>0 teste le solde de la commande pour qu'il ne
soit pas zéro. C'est simplement un filtre qu'on peut enclencher ou pas.


Mais je suis désolé, je n'arrive pas à suivre ta logique.



J'aimerais obtenir:

1) Les entêtes (Contract)
- avec ou sans détails (ContractDetail)
- avec ou sans ID client (liaison vers Address)

2) Les détails relatifs aux entêtes trouvés
- avec ou sans ID Produit (liaison vers Product)

3) Le nom du client, lorsque l'ID est disponible, sinon blanc

4) La désignation du produit, lorsque l'ID est disponible, sinon blanc


Est-elle vraiment si tordue ma logique, ou peut-être mon français trop
rudimentaire? De toute façon, encore merci.
Avatar
mat
Roumegou wrote:

mat avait écrit le 24/04/2004 :

Roumegou wrote:

Volià, j'espère que cela pourra t'aider.




En HF, ton code correspond à

"FROM ContractDetail INNER JOIN Contract on
ContractDetail.IDContract=Contract.IDContract, "+...
"ContractDetail INNER JOIN Product on ContractDetail.IDProduct =
Product.IDProduct, "+...
"Contract LEFT JOIN Address ON Contract.IDCustSupp = Address.IDAddress
"+...
"WHERE Contract.IDContractType < 8 "

Elle marche mais ne donne pas les entêtes sans détails.




cf mon post précédent.
Si tu fais des tests sur des zones de contractdetail (balance par ex),
il ne seront pas satisfaits pour les tuples sans contractdetail (valeur
null).
Attention, peut être cela se passe comme cela avec HF mais si tu passes
sur Oracle par ex, cela ne marchera pas. Autant prendre tout de suite
les bonnes habitudes.




C'est justement ce que je crains. Pourtant, ce n'est pas une question
d'habitudes mais est inevitable dans ce que veux atteindre (que toutes
les données peuvent être récupérés par l'utilisateur après une panne de
courant ou réseau. Il semble que je vais devoir continuer avec ma
requête Union, ayant une partie sans filtre sur le détail.
Avatar
Roumegou
mat a formulé ce dimanche :
Bonsoir Eric,



[CUT]
J'aimerais obtenir:

1) Les entêtes (Contract)
- avec ou sans détails (ContractDetail)
- avec ou sans ID client (liaison vers Address)

2) Les détails relatifs aux entêtes trouvés
- avec ou sans ID Produit (liaison vers Product)

3) Le nom du client, lorsque l'ID est disponible, sinon blanc

4) La désignation du produit, lorsque l'ID est disponible, sinon blanc



Okay pour ce contexte particulier (élément pertubé risque de
désynchonisation).
Dans ce cas, je gèrerais cela par deux requetes.

Je pars des contracts avec adress en left join.
Pour chaque contrat; je lance une requete sur contractdetail avec
produit en left join. Là pas de surprises.

Mais franchement, que tu utilises ces deux requetes ou les left join,
les performances ne seront pas au rdv.?
Pour ma part, (mais encore une fois c'est toi qui connais mieux ton
contexte) avoir des commandes sans détail et des détails sans produits
ne m'interesse pas. Je préfèrerai les ignorer par des inner join,
quitte à faire le ménage de temps en temps avec une requete de type
DELETE CONTRACT WHERE CONTRACTID NOT IN (SELECT DISTINCT CONTRACTID
FROM CONTRACTDETAIL).

Autre chose importante : Le contrôle de validation
Je ne vais pas critiquer HF (on vas encore me reprocher mon ostracisme
;-) ) mais si tu travailles avec un SGBD qui gère les transactions, tu
peux éviter les dysfonctionnements dus aux arrêts intempestifs avec les
commit, rollback)




Est-elle vraiment si tordue ma logique, ou peut-être mon français trop
rudimentaire? De toute façon, encore merci.



Si le français n'est pas ta langue maternelle, permet moi de te
féliciter au contraire.

--
Eric Roumegou
http://cerbermail.com/?TSoulBerPA
(cliquez sur le lien ci-dessus pour me contacter en privé)
Avatar
mat
Roumegou wrote:
mat a formulé ce dimanche :

Bonsoir Eric,



[CUT]

J'aimerais obtenir:

1) Les entêtes (Contract)
- avec ou sans détails (ContractDetail)
- avec ou sans ID client (liaison vers Address)

2) Les détails relatifs aux entêtes trouvés
- avec ou sans ID Produit (liaison vers Product)

3) Le nom du client, lorsque l'ID est disponible, sinon blanc

4) La désignation du produit, lorsque l'ID est disponible, sinon blanc




Okay pour ce contexte particulier (élément pertubé risque de
désynchonisation).
Dans ce cas, je gèrerais cela par deux requetes.

Je pars des contracts avec adress en left join.
Pour chaque contrat; je lance une requete sur contractdetail avec
produit en left join. Là pas de surprises.



OK, ça correspond à ma requête Union.


Mais franchement, que tu utilises ces deux requetes ou les left join,
les performances ne seront pas au rdv.?
Pour ma part, (mais encore une fois c'est toi qui connais mieux ton
contexte) avoir des commandes sans détail et des détails sans produits
ne m'interesse pas. Je préfèrerai les ignorer par des inner join, quitte
à faire le ménage de temps en temps avec une requete de type DELETE
CONTRACT WHERE CONTRACTID NOT IN (SELECT DISTINCT CONTRACTID FROM
CONTRACTDETAIL).



Le problème ne se pose que pour la saisie, pour les états il n'y a que
des Inner Joins. Dans mon modèle, strictement multi-utlisateur, ce type
de requête pourrait provoquer des problèmes. Mais à chacun son truc...


Autre chose importante : Le contrôle de validation
Je ne vais pas critiquer HF (on vas encore me reprocher mon ostracisme
;-) ) mais si tu travailles avec un SGBD qui gère les transactions, tu
peux éviter les dysfonctionnements dus aux arrêts intempestifs avec les
commit, rollback)



Pour autant que que je sache les transactions existent et fonctionnent
avec HF. Mais dans mes yieux, ils ont généralement un désavantage
considérable, et ceci indépendant de la base de données: lorsqu'on
commence avec une saisie ou une modification, on ne sais pas si le
système les acceptera. Dans mon modèle, chaque saisie ou modif commencée
va aboutir (bien sûr sous condition qu'elles passent les vérifications
par l'application). Dans mon opinion, les transactions ça va très bien
quand il s'agit de peu de changements qui doivent absolument être
synchrones, p.ex. un débit/crédit bancaire. Mais dans une gestion avec
des documents qui peuvent avoir plus de 100 positions je préfère savoir
avant de commencer un traitement si je pourra le terminer. Encore une
fois, à chacun son truc...:-)

Et encore un grand merci pour avoir pris le temps d'analyser mon problème.

Mat

P.S. Ma langue maternelle est le suisse-allemand. Ce qui a amélioré un
peu mon français écrit étaient les premiers 2 ans avec WD 7/7.5 quand
j'ai comencé à suivre les NG. Auparavant, je n'avais que rarement besoin
de NG ;-)