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

WD12/MySQL 4.1 - Est ce que c'est possible en SQL ?

18 réponses
Avatar
I.G.LOG
Bonjour à tous,
Je suis en train de construire une requete qui doit me donner les ruptures
de stock d'article.
Il y a rupture pour un article quand : QteC - QteF - QteS < 0
(avec QteC = qté commandée clients, QteF = qté commandée fournisseurs, QteS
= qté stock)

Pour avoir les qtés commandés client (QteC) je fais la requete suivante:

SELECT
documlg.IDARTICLE,
documlg.REFCONST,
documlg.DESIGNATION,
documlg.ETAT,
SUM(QTE) AS QteCli // Me
donne le total commandé par article et état
FROM
documlg
WHERE
documlg.QTE > 0
AND NUMGRP = 3
AND documlg.ETAT BETWEEN 1 AND 2 // Etat neuf et occasion
GROUP BY
IDARTICLE,REFCONST,DESIGNATION,ETAT
HAVING
QteCli > 0
// Ne prend que les articles qui ont une commande client
ORDER BY
REFCONST,ETAT

Mon problème est le suivant:
Je voudrais, dans la même requète, ramener le cumul des commandes
fournisseur (et du stock - mais ne compliquons pas trop pour l'instant) pour
chaque ligne de commande client. J'ai donc rajouté dans la requete une
jointure (left join) sur les lignes de commandes fournisseur comme suit:

SELECT
documlg.IDARTICLE,
documlg.REFCONST,
documlg.DESIGNATION,
documlg.ETAT,
SUM(QTE) AS QteCli,
SUM(cdefou.QTE) as QteFou // Donne le
total commandé fourn (????)
FROM
documlg
LEFT JOIN cdefou
ON cdefou.IDARTICLE = documlg.IDARTICLE
AND cdefou.ETAT = documlg.ETAT // Le même
article
WHERE
documlg.QTEREST > 0
AND NUMGRP = 3
AND documlg.ETAT BETWEEN 1 AND 2
GROUP BY
IDARTICLE,REFCONST,DESIGNATION,ETAT
HAVING
QteCli > QteFou
// Ne prend que les commandes client > cdes fournisseurs
ORDER BY
REFCONST,ETAT

Le problème: cette requete fonctionne, mais ne donne pas les valeurs QteCli
et QteFou escomptées !!!
Il semblerait que les SUM s'appliquent à chaque ligne (ce qui augmente les
valeurs), alors que je voudrais que le GROUP BY se fasse d'abords et ensuite
qu'il effectue les SUM. Est-ce possible ?

Dans mes tests, pour l'article A1633-86, j'ai dans la base 5 en commande
client et 10 en commande fournisseur
La requete me renvoie 20 et 20 ?!

J'espère avoir été assez clair

Merci pour vos idées

8 réponses

1 2
Avatar
I.G.LOG
> les alias ne sont pas genant et permettent de savoir sur quelle union il y
a un probleme le cas echeant

a partir de la tu peux rajouter ce que tu veux

c'est comme ca que j'etais arrivée a une requete de 19 000 lignes
car dans ma requete je faisait un between sur des dates et sur une table
de 900 million de lignes ou avec des OR : c'etait lent
donc je me suis amusé a faire une requete sans OR et sans between qu'avec
des = (puisque les index existaient sur les dates) or avec un between ou
des OR l'index n'est plus utilisé car la date est considérée comme n'etant
pas donnée par le moteur donc il n'utilise pas l'index ou pas correctement
meme avec un force index)

par contre des qu'on met = il utilise l'index (normal il considere qu'on
fourni la valeur)
et donc pour 1 ans j'avais 352 unions (1 par jour)

et tout cela faisait que la requete etait plus rapide car il utilisait le
bon index et donc il faisait 352 * 0,03 = 10 secondes pour monter la
requete et lire parmi 900 millions alors que la premiere requete ne
rendait pas le reultat (du moins j'ai jamais attendu assez longtemps pour
voir si elle rendait le resultat au bout de 2 minutes j'arretais)

voila juste pour l'info




Merci pour ces précisions qui me permettront surement d'optimiser mes
requetes.
Je t'ai posté plus haut un problème sur une addition de résultat issus de
sous-requetes dans une clause having.
...
HAVING
QteCli > ((select sum(qte) from AutreTable where ...) + (select
sum(Qte) from EncoreUneAutre where ...))

donne une erreur sur le + correspondant à l'addition des deux sous-requetes.
Pourtant j'ai vu cette syntaxe fonctionner dans un where par exemple. Ce
n'est pas possible dans la clause HAVING ?

Encore Merci
Avatar
Firetox
dans le where c'est possible mais pas dans le having

le having est fait une fois que la requte est faites c'est a dire que le
select est fait et avant de rendre les ligne le moteur enleve les ligne ne
correspondant pas au having
donc on ne peut plus faire de calcul sur les colonnes des tables mais on
peut le faire sur les colonnes finale de la requete

on ne peut pas faire

select col1 , col2 from ma table
having matable.etat +matable.odre = 4

par contre on peut faire
select col1,col2,etat,ordre
from ma table
having etat+ordre=4

il y a une difference et c'est la qu'on comprend quand le having se fait
il se fait sur le resultat de la requete

donc un sous select ne sera pas permi dans le having

Bon dev
@+

Firetox
"I.G.LOG" a écrit dans le message de news:
48dcb179$0$967$
les alias ne sont pas genant et permettent de savoir sur quelle union il
y a un probleme le cas echeant

a partir de la tu peux rajouter ce que tu veux

c'est comme ca que j'etais arrivée a une requete de 19 000 lignes
car dans ma requete je faisait un between sur des dates et sur une table
de 900 million de lignes ou avec des OR : c'etait lent
donc je me suis amusé a faire une requete sans OR et sans between qu'avec
des = (puisque les index existaient sur les dates) or avec un between ou
des OR l'index n'est plus utilisé car la date est considérée comme
n'etant pas donnée par le moteur donc il n'utilise pas l'index ou pas
correctement meme avec un force index)

par contre des qu'on met = il utilise l'index (normal il considere qu'on
fourni la valeur)
et donc pour 1 ans j'avais 352 unions (1 par jour)

et tout cela faisait que la requete etait plus rapide car il utilisait le
bon index et donc il faisait 352 * 0,03 = 10 secondes pour monter la
requete et lire parmi 900 millions alors que la premiere requete ne
rendait pas le reultat (du moins j'ai jamais attendu assez longtemps pour
voir si elle rendait le resultat au bout de 2 minutes j'arretais)

voila juste pour l'info




Merci pour ces précisions qui me permettront surement d'optimiser mes
requetes.
Je t'ai posté plus haut un problème sur une addition de résultat issus de
sous-requetes dans une clause having.
...
HAVING
QteCli > ((select sum(qte) from AutreTable where ...) + (select
sum(Qte) from EncoreUneAutre where ...))

donne une erreur sur le + correspondant à l'addition des deux
sous-requetes.
Pourtant j'ai vu cette syntaxe fonctionner dans un where par exemple. Ce
n'est pas possible dans la clause HAVING ?

Encore Merci




Avatar
I.G.LOG
> dans le where c'est possible mais pas dans le having

le having est fait une fois que la requte est faites c'est a dire que le
select est fait et avant de rendre les ligne le moteur enleve les ligne ne
correspondant pas au having
donc on ne peut plus faire de calcul sur les colonnes des tables mais on
peut le faire sur les colonnes finale de la requete

on ne peut pas faire

select col1 , col2 from ma table
having matable.etat +matable.odre = 4

par contre on peut faire
select col1,col2,etat,ordre
from ma table
having etat+ordre=4

il y a une difference et c'est la qu'on comprend quand le having se fait
il se fait sur le resultat de la requete

donc un sous select ne sera pas permi dans le having

Bon dev
@+




J'en demandais trop au SQL donc.
Encore merci pour tout et bon dev.
A+
Phil
Avatar
Firetox
>J'en demandais trop au SQL donc.


non il suffit de savoir ou mettre le sous select pour pouvoir avoir l'info
dans le having
c'est faisable mais de la bonne façon

Bon dev
@+



"I.G.LOG" a écrit dans le message de news:
48dcb90a$0$910$

dans le where c'est possible mais pas dans le having

le having est fait une fois que la requte est faites c'est a dire que le
select est fait et avant de rendre les ligne le moteur enleve les ligne
ne correspondant pas au having
donc on ne peut plus faire de calcul sur les colonnes des tables mais on
peut le faire sur les colonnes finale de la requete

on ne peut pas faire

select col1 , col2 from ma table
having matable.etat +matable.odre = 4

par contre on peut faire
select col1,col2,etat,ordre
from ma table
having etat+ordre=4

il y a une difference et c'est la qu'on comprend quand le having se fait
il se fait sur le resultat de la requete

donc un sous select ne sera pas permi dans le having

Bon dev
@+




J'en demandais trop au SQL donc.
Encore merci pour tout et bon dev.
A+
Phil



Avatar
I.G.LOG
> non il suffit de savoir ou mettre le sous select pour pouvoir avoir l'info
dans le having
c'est faisable mais de la bonne façon



Je vais creuser ça.
Je reviens à l'autre requete UNION. maintenant c'est Windev qui m'embete.
J'ai un warning sur la requete finale (qui fonctionne avec frontal MySQL et
avec SQLExec() )
"Warning : L'utilisation de fonctions agrégats avec d'autres rubriques ou
fonctions non agrégat n'est pas autorisée sans l'utilisation d'une clause
GROUP BY. Toutes les rubriques ou fonctions non agrégat doivent figurer dans
la clause GROUP BY.
RStRupt, Code SQL, ligne 1, colonne 1"
Pourtant j'ai bien le GROUP BY final ?!
et je ne peux pas l'exécuter par GO (ni avec hExecuteRequete donc)
Ca bloque justement sur le ...) as TableVirt !!! Dès que j'enlève ça, je
n'ai plus l'erreur.
As tu une idée ?

Pour rappel voici la requete:

SELECT
IDART,REF,DESIGN,NS,SUM(QteCli) AS CDECLI,SUM(QteFou) AS CDEFOU
FROM
(
(SELECT
L1.IDARTICLE AS IDART,L1.REFCONST AS REF,L1.DESIGNATION AS
DESIGN,L1.ETAT AS NS,SUM(L1.QTEREST) AS QteCli,0 AS QteFou
FROM
documlg AS L1
INNER JOIN docum AS D1
ON D1.IDDOCUM = L1.IDDOCUM
AND D1.EMIS = 0
AND D1.IDDOCUM IN (SELECT A1.IDDOCUM FROM action AS A1)
INNER JOIN type AS T1
ON T1.IDTYPE = D1.IDTYPE
AND T1.DESIGNATION = 'Commande'
WHERE
L1.QTEREST > 0
AND L1.NUMGRP = 3
AND L1.ETAT BETWEEN 1 AND 2
GROUP BY
IDART,REF,DESIGN,NS,QteFou
HAVING
QteCli > 0
)
UNION
(SELECT
L2.IDARTICLE AS IDART,L2.REFCONST AS REF,L2.DESIGNATION AS
DESIGN,L2.ETAT AS NS,0 AS QteCli,SUM(L2.QTEREST) AS QteFou
FROM
documlg AS L2
INNER JOIN docum AS D2
ON D2.IDDOCUM = L2.IDDOCUM
AND D2.EMIS = 1
AND D2.IDDOCUM IN (SELECT A2.IDDOCUM FROM action AS A2)
INNER JOIN type AS T2
ON T2.IDTYPE = D2.IDTYPE
AND T2.DESIGNATION = 'Commande'
WHERE
L2.QTEREST > 0
AND L2.NUMGRP = 3
AND L2.ETAT BETWEEN 1 AND 2
GROUP BY
IDART,REF,DESIGN,NS
HAVING
QteFou > 0
)
) AS TableVirt // J'ai un warning windev ici
!!!
GROUP BY
IDART,REF,DESIGN,NS
ORDER BY
REF,NS
Avatar
Firetox
il ne faut pas que windev interprete la requete il doit la laisser passer
sans faire de corection comme SQLExec
donc dans hexecuteRequete tu dois avoir un parametre pour dire a windev de
laisser paser la requete
voir hsanscorrection

bon dev
@+

Firetox

"I.G.LOG" a écrit dans le message de news:
48dcbdd2$0$895$
non il suffit de savoir ou mettre le sous select pour pouvoir avoir
l'info dans le having
c'est faisable mais de la bonne façon



Je vais creuser ça.
Je reviens à l'autre requete UNION. maintenant c'est Windev qui m'embete.
J'ai un warning sur la requete finale (qui fonctionne avec frontal MySQL
et avec SQLExec() )
"Warning : L'utilisation de fonctions agrégats avec d'autres rubriques ou
fonctions non agrégat n'est pas autorisée sans l'utilisation d'une clause
GROUP BY. Toutes les rubriques ou fonctions non agrégat doivent figurer
dans la clause GROUP BY.
RStRupt, Code SQL, ligne 1, colonne 1"
Pourtant j'ai bien le GROUP BY final ?!
et je ne peux pas l'exécuter par GO (ni avec hExecuteRequete donc)
Ca bloque justement sur le ...) as TableVirt !!! Dès que j'enlève ça, je
n'ai plus l'erreur.
As tu une idée ?

Pour rappel voici la requete:

SELECT
IDART,REF,DESIGN,NS,SUM(QteCli) AS CDECLI,SUM(QteFou) AS CDEFOU
FROM
(
(SELECT
L1.IDARTICLE AS IDART,L1.REFCONST AS REF,L1.DESIGNATION AS
DESIGN,L1.ETAT AS NS,SUM(L1.QTEREST) AS QteCli,0 AS QteFou
FROM
documlg AS L1
INNER JOIN docum AS D1
ON D1.IDDOCUM = L1.IDDOCUM
AND D1.EMIS = 0
AND D1.IDDOCUM IN (SELECT A1.IDDOCUM FROM action AS A1)
INNER JOIN type AS T1
ON T1.IDTYPE = D1.IDTYPE
AND T1.DESIGNATION = 'Commande'
WHERE
L1.QTEREST > 0
AND L1.NUMGRP = 3
AND L1.ETAT BETWEEN 1 AND 2
GROUP BY
IDART,REF,DESIGN,NS,QteFou
HAVING
QteCli > 0
)
UNION
(SELECT
L2.IDARTICLE AS IDART,L2.REFCONST AS REF,L2.DESIGNATION AS
DESIGN,L2.ETAT AS NS,0 AS QteCli,SUM(L2.QTEREST) AS QteFou
FROM
documlg AS L2
INNER JOIN docum AS D2
ON D2.IDDOCUM = L2.IDDOCUM
AND D2.EMIS = 1
AND D2.IDDOCUM IN (SELECT A2.IDDOCUM FROM action AS A2)
INNER JOIN type AS T2
ON T2.IDTYPE = D2.IDTYPE
AND T2.DESIGNATION = 'Commande'
WHERE
L2.QTEREST > 0
AND L2.NUMGRP = 3
AND L2.ETAT BETWEEN 1 AND 2
GROUP BY
IDART,REF,DESIGN,NS
HAVING
QteFou > 0
)
) AS TableVirt // J'ai un warning windev
ici !!!
GROUP BY
IDART,REF,DESIGN,NS
ORDER BY
REF,NS



Avatar
I.G.LOG
"Firetox" a écrit dans le message de news:
48dcbf22$0$16475$
il ne faut pas que windev interprete la requete il doit la laisser passer
sans faire de corection comme SQLExec
donc dans hexecuteRequete tu dois avoir un parametre pour dire a windev de
laisser paser la requete
voir hsanscorrection




oui bien sur, mais je ne peux pas la tester. Et, de plus, cette requete me
sert pour un état "basé sur une requete du projet". J'ai peur que l'état ne
s'exécute pas. Enfin, je vais essayer et je te dirais ce que ça donne.
A+ et bon app.
Avatar
I.G.LOG
En effet, l'état ne s'exécute pas :-(
Je vais peut-être me tourner vers le ST PC-Soft. Trop de galères avec ces
états basés sur requetes du projet... mais sans grand espoir, j'ai déjà
transmis ce genre de problème sans réponse disons "convenable"
1 2