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

10 réponses

1 2
Avatar
I.G.LOG
Pas beaucoup de réponses, le problème doit être ardu.
Pour faire plus simple, est-il possible en SQL de faire un SUM(AutreTable)
après le GROUP BY ?
Encore merci
Avatar
Firetox
bonjour,

il faut faire une union
si tes 2 requetes te donnent le bon resultat separement il suffit de faire
l'union des 2
qui remontera la somme sur les 2 en une seule ligne

faire la requete qui te donne les commande cli avec le group by par article
faire une requete qui te donne les quantie commande par four group by
article

penser a mettre dans chaque requete les colonne identique et mettre 0 a
CdeFour dans la premiere
et 0 as cdeCli dans la deuxieme

faire le order a la fin de l'union

ensuite cette union sert de table (comme une vue pour faire un select (avec
sum et gourp by idem
que precedement qui fera ce que tu veux

car l'union va remonte 2 ligne par article 1 pour les clients et 2 pour les
four
le select (sous select en fait ) peut faire de ces 2 lignes 2 seule ligne

bref pour etre clair il faudrait la requete sur les four car la premiere
peut rester comme ca
mais je ne connais pas la structure et donc la deuxieme je ne peux pas
l'ecrire et te donner l'ensemble


Bon dev
@+

Firetox


"I.G.LOG" a écrit dans le message de news:
48dbcfce$0$925$
Pas beaucoup de réponses, le problème doit être ardu.
Pour faire plus simple, est-il possible en SQL de faire un SUM(AutreTable)
après le GROUP BY ?
Encore merci



Avatar
I.G.LOG
Bonjour FireTox
Voici la requete avec UNION (un peu compliquée mais qui fonctionne - le 1er
select me donne les commandes clients, le 2eme les commandes fournisseurs)

SELECT
documlg.IDARTICLE,documlg.REFCONST,documlg.DESIGNATION,documlg.ETAT,SUM(QTEREST)AS QteCli,0 as QteFouFROM documlg INNER JOIN docum ON docum.IDDOCUM = documlg.IDDOCUM AND docum.EMIS = 0 AND docum.IDDOCUM IN (SELECT IDDOCUM FROM action) INNER JOIN type ON type.IDTYPE = docum.IDTYPE AND type.DESIGNATION = 'Commande'WHERE documlg.QTEREST > 0 AND NUMGRP = 3 AND documlg.ETAT BETWEEN 1 AND 2GROUP BY IDARTICLE,REFCONST,DESIGNATION,ETATHAVING QteCli > 0UNIONSELECT documlg.IDARTICLE,documlg.REFCONST,documlg.DESIGNATION,documlg.ETAT,0 asQteCli,SUM(QTEREST) AS QteFouFROM documlg INNER JOIN docum ON docum.IDDOCUM = documlg.IDDOCUM AND docum.EMIS = 1 AND docum.IDDOCUM IN (SELECT IDDOCUM FROM action) INNER JOIN type ON type.IDTYPE = docum.IDTYPE AND type.DESIGNATION = 'Commande'WHERE documlg.QTEREST > 0 AND NUMGRP = 3 AND documlg.ETAT BETWEEN 1 AND 2GROUP BY IDARTICLE,REFCONST,DESIGNATION,ETATHAVING Qtefou > 0ORDER BY REFCONST,ETATLe problème c'est que je n'ai pas les valeurs sur la même ligne: j'aimeraisbien avoir sur la même ligne QteCli et QteFouEncore Merci
Avatar
I.G.LOG
la requete avec UNION


SELECT
documlg.IDARTICLE,documlg.REFCONST,documlg.DESIGNATION,documlg.ETAT,SUM(QTEREST)AS
QteCli,0 as QteFou
FROM
documlg
INNER JOIN docum
ON docum.IDDOCUM = documlg.IDDOCUM
AND docum.EMIS = 0
AND docum.IDDOCUM IN (SELECT IDDOCUM FROM action)
INNER JOIN type
ON type.IDTYPE = docum.IDTYPE
AND type.DESIGNATION = 'Commande'
WHERE
documlg.QTEREST > 0
AND NUMGRP = 3
AND documlg.ETAT BETWEEN 1 AND 2
GROUP BY
IDARTICLE,REFCONST,DESIGNATION,ETAT
HAVING
QteCli > 0
UNION
SELECT
documlg.IDARTICLE,documlg.REFCONST,documlg.DESIGNATION,documlg.ETAT,0
asQteCli,SUM(QTEREST) AS QteFou
FROM
documlg
INNER JOIN docum
ON docum.IDDOCUM = documlg.IDDOCUM
AND docum.EMIS = 1
AND docum.IDDOCUM IN (SELECT IDDOCUM FROM action)
INNER JOIN type
ON type.IDTYPE = docum.IDTYPE
AND type.DESIGNATION = 'Commande'
WHERE
documlg.QTEREST > 0
AND NUMGRP = 3
AND documlg.ETAT BETWEEN 1 AND 2
GROUP BY
IDARTICLE,REFCONST,DESIGNATION,ETAT
HAVING
Qtefou > 0
ORDER BY
REFCONST,ETAT
Avatar
I.G.LOG
Un autre problème sur GROUP BY et HAVING: j'essaie de tester le resultat du
having avec l'addition du résultat de deux sous requete, mais j'ai une
erreur MySQL

...
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
maintenant il te reste plus qu'a faire un select de tout ca
met des as sur tes colonne dans les select de l'union

par ex

select nom, sum(cli),sum(four)
from (

Select maCol as nom, sum(qte) as cli, 0 as four
from ......

uninon

Select maCol as nom, 0 as cli , sum(qteFour) as four
from ......

)
grop by nom

voila le principe est la
tu as deux lignes pour l'instant avec ce mecanisme tu en auras une avec les
données de l'union
donc il te reste juste a ajote un select et une paranthese et un group by et
tu devrait avoir ton resultat

donc tu y est presque
"I.G.LOG" a écrit dans le message de news:
48dbe0ae$0$867$
la requete avec UNION


SELECT

documlg.IDARTICLE,documlg.REFCONST,documlg.DESIGNATION,documlg.ETAT,SUM(QTEREST)AS
QteCli,0 as QteFou
FROM
documlg
INNER JOIN docum
ON docum.IDDOCUM = documlg.IDDOCUM
AND docum.EMIS = 0
AND docum.IDDOCUM IN (SELECT IDDOCUM FROM action)
INNER JOIN type
ON type.IDTYPE = docum.IDTYPE
AND type.DESIGNATION = 'Commande'
WHERE
documlg.QTEREST > 0
AND NUMGRP = 3
AND documlg.ETAT BETWEEN 1 AND 2
GROUP BY
IDARTICLE,REFCONST,DESIGNATION,ETAT
HAVING
QteCli > 0
UNION
SELECT
documlg.IDARTICLE,documlg.REFCONST,documlg.DESIGNATION,documlg.ETAT,0
asQteCli,SUM(QTEREST) AS QteFou
FROM
documlg
INNER JOIN docum
ON docum.IDDOCUM = documlg.IDDOCUM
AND docum.EMIS = 1
AND docum.IDDOCUM IN (SELECT IDDOCUM FROM action)
INNER JOIN type
ON type.IDTYPE = docum.IDTYPE
AND type.DESIGNATION = 'Commande'
WHERE
documlg.QTEREST > 0
AND NUMGRP = 3
AND documlg.ETAT BETWEEN 1 AND 2
GROUP BY
IDARTICLE,REFCONST,DESIGNATION,ETAT
HAVING
Qtefou > 0
ORDER BY
REFCONST,ETAT



Avatar
I.G.LOG
Bonjour,
J'ai une erreur 1248 en rajoutant simplement un SELECT Alias1,Alias2... FROM
(... UNION ...)
J'ai tout essayé sans succès: aliasser toutes les tables, tous les champs...
rien n'y fait j'ai l'erreur "[Serveur] ERREUR 1248: Every derived table must
have its own alias"
Voici la "dernière" requete que j'ai essayée (sans succès, tjrs la même
erreur):

SELECT
IDART1,REF1,DESIGN1,ETAT1,SUM(QteCli1), SUM(QteFou2)
FROM
(
(SELECT
L1.IDARTICLE as IDART1,L1.REFCONST as REF1,L1.DESIGNATION as
DESIGN1,L1.ETAT as ETAT1,SUM(L1.QTEREST) AS QteCli1,0 AS QteFou1
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)
UNION
(SELECT
L2.IDARTICLE as IDART2,L2.REFCONST as REF2,L2.DESIGNATION as
DESIGN2,L2.ETAT as ETAT2,0 AS QteCli2,SUM(L2.QTEREST) AS QteFou2
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
IDART1,REF1,DESIGN1,ETAT1

J'ai même essayé ... FROM ( (SELECT ...) as Table1 UNION (SELECT ...) as
Table2) et là j'ai une erreur "[Serveur] ERREUR 1064: You have an error in
your SQL syntax; check the manual that corresponds to your MySQL server
version for the right syntax to use near 'as Table1 UNION (SELECT
L2.IDARTICLE as IDART2,L2.REFCONST as R' at line 18"
Avatar
I.G.LOG
Ca y est j'ai trouvé (après avoir bien "transpiré" - c'est assez tordu quand
même), ca marche en rajoutant un alias sur le SELECT principal
SELECT ch1,ch2... FROM ((SELECT ...) UNION (SELECT ...)) as TableVirt GROUP
BY... ORDER BY...

Voici la requete:
SELECT
IDART,REF,DESIGN,NS,SUM(QteCli),SUM(QteFou)
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
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
GROUP BY
IDART,REF,DESIGN,NS
ORDER BY
REF,NS

Prochaines étapes: voir si je peux enlever les alias sur les tables
(D1,D2...) et rajouter une UNION sur les lignes de stock.
Un grand merci à toi, tu m'as - une nouvelle fois - rendu un grand service.
Avatar
Firetox
oui j'avais oublie de le dire

quand tu fait un select d'un select il faut lui donné un alias comme si on
avait crée une tble temporaire ou une vue et le select principal reprend cet
alias pour les nom de colonne a remonté
car si tu n'a pas droit au sous select il ya 5 ans pour faire cela il
fallait creer une temporary table ou faire une vue suivant le moteur SGBD
avec les sous select c'est plus simple car on a pas besoin de creer une vue
ou une table temporaire, mais cote serveur il fait la meme chose qu'une vue.

bon dev
@+


"I.G.LOG" a écrit dans le message de news:
48dc79cf$0$896$
Ca y est j'ai trouvé (après avoir bien "transpiré" - c'est assez tordu
quand même), ca marche en rajoutant un alias sur le SELECT principal
SELECT ch1,ch2... FROM ((SELECT ...) UNION (SELECT ...)) as TableVirt
GROUP BY... ORDER BY...

Voici la requete:
SELECT
IDART,REF,DESIGN,NS,SUM(QteCli),SUM(QteFou)
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
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
GROUP BY
IDART,REF,DESIGN,NS
ORDER BY
REF,NS

Prochaines étapes: voir si je peux enlever les alias sur les tables
(D1,D2...) et rajouter une UNION sur les lignes de stock.
Un grand merci à toi, tu m'as - une nouvelle fois - rendu un grand
service.



Avatar
Firetox
>Prochaines étapes: voir si je peux enlever les alias sur les tables
(D1,D2...) et rajouter une UNION sur les lignes de stock.
Un grand merci à toi, tu m'as - une nouvelle fois - rendu un grand service.



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

Bon dev
@+


"I.G.LOG" a écrit dans le message de news:
48dc79cf$0$896$
Ca y est j'ai trouvé (après avoir bien "transpiré" - c'est assez tordu
quand même), ca marche en rajoutant un alias sur le SELECT principal
SELECT ch1,ch2... FROM ((SELECT ...) UNION (SELECT ...)) as TableVirt
GROUP BY... ORDER BY...

Voici la requete:
SELECT
IDART,REF,DESIGN,NS,SUM(QteCli),SUM(QteFou)
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
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
GROUP BY
IDART,REF,DESIGN,NS
ORDER BY
REF,NS

Prochaines étapes: voir si je peux enlever les alias sur les tables
(D1,D2...) et rajouter une UNION sur les lignes de stock.
Un grand merci à toi, tu m'as - une nouvelle fois - rendu un grand
service.



1 2