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

Problème de requête SQL

6 réponses
Avatar
jack
Bonjour,

J'ai une table marchandise
MARC_ID int
MARC_LIBELLE varchar(80)
...

Une table mouvement

MOUV_ID int
MARC_ID int
MOUV_DATE datetime
MOUV_PA decimal(18,2)
MOUV_PR decimal (18,2)
...

La table mouvement recensant tous les mouvements de la table marchandise.

J'essaie d'obtenir les dernières dates de mouvement, PA et PR pour les
marchandises.
Si je fais

select distinct m.MARC_ID, m.MARC_LIBELLE, mv.MOUV_DATE, mv._MOUV_PA ,
mv_MOUV_PR
from MARCHANDISE m
left outer join (select top 1 * from mouvement order by MOUV_DATE desc) mv
on m.MARC_ID=mv.MARC_ID

je n'obtiens évidemment que le dernier mouvement de la table et non le
dernier mouvement pour chaque article

Si je fais left outer join (select top 1 * from mouvement where
m1.MARC_ID=m.MARC_ID order by MOUV_DATE desc) mv
Ca ne marche pas non plus (le deuxième m.MARC_ID est inconnu)


Et je voudrais éviter d'avoir à faire 3 fois la même requête en mettant
quelque chose du genre

select distinct
m.MARC_ID,m.MARC_CODETRI,m.MARC_CODEARTICLE,m.MARC_DESIGNATION,

MOUV_DATE=(select top 1 MOUV_DATE from mouvement mv where mv.MARC_ID =
m.MARC_ID order by mv.MOUV_DATE desc),
MARC_PA=(select top 1 MOUV_PA from mouvement mv where mv.MARC_ID = m.MARC_ID
order by mv.MOUV_DATE desc),
MARC_PR=(select top 1 MOUV_PR from mouvement mv where mv.MARC_ID = m.MARC_ID
order by mv.MOUV_DATE desc)
from MARCHANDISE m


Comment puis-je faire ?

Merci par avance

6 réponses

Avatar
OokieDookie
Bonjour,

Essayez ceci (non testé)

SELECT
m.MARC_ID,
m.MARC_CODETRI,
m.MARC_CODEARTICLE,
m.MARC_DESIGNATION,
MAX(m2.MOUV_DATE) AS MOUV_DATE,
MAX(m3.MOUV_PA) AS MOUV_PA,
MAX(m4.MOUV_PR) AS MOUV_PR
FROM
MARCHANDISE m
LEFT OUTER JOIN
MOUVEMENT m2
ON
m.MARC_ID = m2.MARC_ID
LEFT OUTER JOIN
MOUVMENT m3
ON
m.MARC_ID = m3.MARC_ID
LEFT OUTER JOIN
MOUVMENT m4
ON
m.MARC_ID = m4.MARC_ID
GROUP BY
m.MARC_ID,
m.MARC_CODETRI,
m.MARC_CODEARTICLE,
m.MARC_DESIGNATION
ORDER BY
m.MARC_CODEARTICLE


HTH,

"jack" a écrit :

Bonjour,

J'ai une table marchandise
MARC_ID int
MARC_LIBELLE varchar(80)
....

Une table mouvement

MOUV_ID int
MARC_ID int
MOUV_DATE datetime
MOUV_PA decimal(18,2)
MOUV_PR decimal (18,2)
....

La table mouvement recensant tous les mouvements de la table marchandise.

J'essaie d'obtenir les dernières dates de mouvement, PA et PR pour les
marchandises.
Si je fais

select distinct m.MARC_ID, m.MARC_LIBELLE, mv.MOUV_DATE, mv._MOUV_PA ,
mv_MOUV_PR
from MARCHANDISE m
left outer join (select top 1 * from mouvement order by MOUV_DATE desc) mv
on m.MARC_ID=mv.MARC_ID

je n'obtiens évidemment que le dernier mouvement de la table et non le
dernier mouvement pour chaque article

Si je fais left outer join (select top 1 * from mouvement where
m1.MARC_ID=m.MARC_ID order by MOUV_DATE desc) mv
Ca ne marche pas non plus (le deuxième m.MARC_ID est inconnu)


Et je voudrais éviter d'avoir à faire 3 fois la même requête en mettant
quelque chose du genre

select distinct
m.MARC_ID,m.MARC_CODETRI,m.MARC_CODEARTICLE,m.MARC_DESIGNATION,

MOUV_DATE=(select top 1 MOUV_DATE from mouvement mv where mv.MARC_ID > m.MARC_ID order by mv.MOUV_DATE desc),
MARC_PA=(select top 1 MOUV_PA from mouvement mv where mv.MARC_ID = m.MARC_ID
order by mv.MOUV_DATE desc),
MARC_PR=(select top 1 MOUV_PR from mouvement mv where mv.MARC_ID = m.MARC_ID
order by mv.MOUV_DATE desc)
from MARCHANDISE m


Comment puis-je faire ?

Merci par avance





Avatar
jack
Bonjour,

Ca risque de me renvoyer le plus grand MOUV_PA et MOUV_PR des mouvements
mais pas le MOUV_PA et MOUV_PR correspondant au plus grand MOUV_DATE (le
max(MOUV_DATE))

Non ?


"OokieDookie" wrote in message
news:
Bonjour,

Essayez ceci (non testé)

SELECT
m.MARC_ID,
m.MARC_CODETRI,
m.MARC_CODEARTICLE,
m.MARC_DESIGNATION,
MAX(m2.MOUV_DATE) AS MOUV_DATE,
MAX(m3.MOUV_PA) AS MOUV_PA,
MAX(m4.MOUV_PR) AS MOUV_PR
FROM
MARCHANDISE m
LEFT OUTER JOIN
MOUVEMENT m2
ON
m.MARC_ID = m2.MARC_ID
LEFT OUTER JOIN
MOUVMENT m3
ON
m.MARC_ID = m3.MARC_ID
LEFT OUTER JOIN
MOUVMENT m4
ON
m.MARC_ID = m4.MARC_ID
GROUP BY
m.MARC_ID,
m.MARC_CODETRI,
m.MARC_CODEARTICLE,
m.MARC_DESIGNATION
ORDER BY
m.MARC_CODEARTICLE


HTH,

"jack" a écrit :

> Bonjour,
>
> J'ai une table marchandise
> MARC_ID int
> MARC_LIBELLE varchar(80)
> ....
>
> Une table mouvement
>
> MOUV_ID int
> MARC_ID int
> MOUV_DATE datetime
> MOUV_PA decimal(18,2)
> MOUV_PR decimal (18,2)
> ....
>
> La table mouvement recensant tous les mouvements de la table


marchandise.
>
> J'essaie d'obtenir les dernières dates de mouvement, PA et PR pour les
> marchandises.
> Si je fais
>
> select distinct m.MARC_ID, m.MARC_LIBELLE, mv.MOUV_DATE, mv._MOUV_PA ,
> mv_MOUV_PR
> from MARCHANDISE m
> left outer join (select top 1 * from mouvement order by MOUV_DATE desc)


mv
> on m.MARC_ID=mv.MARC_ID
>
> je n'obtiens évidemment que le dernier mouvement de la table et non le
> dernier mouvement pour chaque article
>
> Si je fais left outer join (select top 1 * from mouvement where
> m1.MARC_ID=m.MARC_ID order by MOUV_DATE desc) mv
> Ca ne marche pas non plus (le deuxième m.MARC_ID est inconnu)
>
>
> Et je voudrais éviter d'avoir à faire 3 fois la même requête en mettant
> quelque chose du genre
>
> select distinct
> m.MARC_ID,m.MARC_CODETRI,m.MARC_CODEARTICLE,m.MARC_DESIGNATION,
>
> MOUV_DATE=(select top 1 MOUV_DATE from mouvement mv where mv.MARC_ID > > m.MARC_ID order by mv.MOUV_DATE desc),
> MARC_PA=(select top 1 MOUV_PA from mouvement mv where mv.MARC_ID m.MARC_ID
> order by mv.MOUV_DATE desc),
> MARC_PR=(select top 1 MOUV_PR from mouvement mv where mv.MARC_ID m.MARC_ID
> order by mv.MOUV_DATE desc)
> from MARCHANDISE m
>
>
> Comment puis-je faire ?
>
> Merci par avance
>
>
>


Avatar
Sylvain Lafontaine
Avec SQL-2000, la solution habituelle consiste à transformer votre requête
actuelle en sous-requête et de ne retourner dedans que la clef primaire de
votre table mouvance. À partir de cette clef, vous pouvez joindre votre
sous-rêquete avec la table Mouvance et aller chercher les autres valeurs
manquantes sans avoir à répéter les requêtes TOP 1.

Avec SQL-2005 et 2008, vous pouvez remplacer l'utilisation de TOP 1 par un
appel à la fonction ROW_NUMBER() et en filtrant les valeurs retournées par
cette fonction égalant 1. Il y a d'innombrables example d'utilisation de
cette fonction dans les newsgroups anglophones ainsi qu'ailleurs sur le web.

Finalement, toujours avec les version 2005/8, vous pouvez utiliser la
méthode CROSS APPLY. Pour un example avec CROSS APPLY ainsi que pour
d'autres examples de méthode, lisez l'article suivant:

http://sqlblog.com/blogs/adam_machanic/archive/2008/02/08/who-s-on-first-solving-the-top-per-group-problem-part-1-technique.aspx

Si vous êtes sur SQL-2005/8, ma préférence personnelle irait avec
l'utilisation de ROW_NUMBER().

--
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.


"jack" wrote in message
news:
Bonjour,

Ca risque de me renvoyer le plus grand MOUV_PA et MOUV_PR des mouvements
mais pas le MOUV_PA et MOUV_PR correspondant au plus grand MOUV_DATE (le
max(MOUV_DATE))

Non ?


"OokieDookie" wrote in message
news:
Bonjour,

Essayez ceci (non testé)

SELECT
m.MARC_ID,
m.MARC_CODETRI,
m.MARC_CODEARTICLE,
m.MARC_DESIGNATION,
MAX(m2.MOUV_DATE) AS MOUV_DATE,
MAX(m3.MOUV_PA) AS MOUV_PA,
MAX(m4.MOUV_PR) AS MOUV_PR
FROM
MARCHANDISE m
LEFT OUTER JOIN
MOUVEMENT m2
ON
m.MARC_ID = m2.MARC_ID
LEFT OUTER JOIN
MOUVMENT m3
ON
m.MARC_ID = m3.MARC_ID
LEFT OUTER JOIN
MOUVMENT m4
ON
m.MARC_ID = m4.MARC_ID
GROUP BY
m.MARC_ID,
m.MARC_CODETRI,
m.MARC_CODEARTICLE,
m.MARC_DESIGNATION
ORDER BY
m.MARC_CODEARTICLE


HTH,

"jack" a écrit :

> Bonjour,
>
> J'ai une table marchandise
> MARC_ID int
> MARC_LIBELLE varchar(80)
> ....
>
> Une table mouvement
>
> MOUV_ID int
> MARC_ID int
> MOUV_DATE datetime
> MOUV_PA decimal(18,2)
> MOUV_PR decimal (18,2)
> ....
>
> La table mouvement recensant tous les mouvements de la table


marchandise.
>
> J'essaie d'obtenir les dernières dates de mouvement, PA et PR pour les
> marchandises.
> Si je fais
>
> select distinct m.MARC_ID, m.MARC_LIBELLE, mv.MOUV_DATE, mv._MOUV_PA ,
> mv_MOUV_PR
> from MARCHANDISE m
> left outer join (select top 1 * from mouvement order by MOUV_DATE desc)


mv
> on m.MARC_ID=mv.MARC_ID
>
> je n'obtiens évidemment que le dernier mouvement de la table et non le
> dernier mouvement pour chaque article
>
> Si je fais left outer join (select top 1 * from mouvement where
> m1.MARC_ID=m.MARC_ID order by MOUV_DATE desc) mv
> Ca ne marche pas non plus (le deuxième m.MARC_ID est inconnu)
>
>
> Et je voudrais éviter d'avoir à faire 3 fois la même requête en mettant
> quelque chose du genre
>
> select distinct
> m.MARC_ID,m.MARC_CODETRI,m.MARC_CODEARTICLE,m.MARC_DESIGNATION,
>
> MOUV_DATE=(select top 1 MOUV_DATE from mouvement mv where mv.MARC_ID >> > m.MARC_ID order by mv.MOUV_DATE desc),
> MARC_PA=(select top 1 MOUV_PA from mouvement mv where mv.MARC_ID > m.MARC_ID
> order by mv.MOUV_DATE desc),
> MARC_PR=(select top 1 MOUV_PR from mouvement mv where mv.MARC_ID > m.MARC_ID
> order by mv.MOUV_DATE desc)
> from MARCHANDISE m
>
>
> Comment puis-je faire ?
>
> Merci par avance
>
>
>






Avatar
Fred BROUARD
En principe ceci devrait suffire :

SELECT MVT.*, MARC_LIBELLE
FROM mouvement AS MVT
INNER JOIN (SELECT MC.MARC_ID, MC.MARC_LIBELLE, MV.MAX_DATE
FROM marchandise AS MC
INNER JOIN (SELECT M.MARC_ID, MAX(MOUV_DATE)
AS MAX_DATE
FROM mouvement AS M
GROUP BY M.MARC_ID) AS MV
ON MC.MARC_ID = MV.MARC_ID ) AS T
ON MVT.MARC_ID = T.MARC_ID
AND MVT.MOUV_DATE = T.MAX_DATE

A +

--
Frédéric BROUARD, MVP SQL Server, expert bases de données et langage SQL
Le site sur le langage SQL et les SGBDR : http://sqlpro.developpez.com
Audit, conseil, expertise, formation, modélisation, tuning, optimisation
Enseignant aux Arts & Métiers PACA et à L'ISEN Toulon - Var Technologies
*********************** http://www.sqlspot.com *************************


jack a écrit :
Bonjour,

J'ai une table marchandise
MARC_ID int
MARC_LIBELLE varchar(80)
...

Une table mouvement

MOUV_ID int
MARC_ID int
MOUV_DATE datetime
MOUV_PA decimal(18,2)
MOUV_PR decimal (18,2)
...

La table mouvement recensant tous les mouvements de la table marchandise.

J'essaie d'obtenir les dernières dates de mouvement, PA et PR pour les
marchandises.
Si je fais

select distinct m.MARC_ID, m.MARC_LIBELLE, mv.MOUV_DATE, mv._MOUV_PA ,
mv_MOUV_PR
from MARCHANDISE m
left outer join (select top 1 * from mouvement order by MOUV_DATE desc) mv
on m.MARC_ID=mv.MARC_ID

je n'obtiens évidemment que le dernier mouvement de la table et non le
dernier mouvement pour chaque article

Si je fais left outer join (select top 1 * from mouvement where
m1.MARC_ID=m.MARC_ID order by MOUV_DATE desc) mv
Ca ne marche pas non plus (le deuxième m.MARC_ID est inconnu)


Et je voudrais éviter d'avoir à faire 3 fois la même requête en mettant
quelque chose du genre

select distinct
m.MARC_ID,m.MARC_CODETRI,m.MARC_CODEARTICLE,m.MARC_DESIGNATION,

MOUV_DATE=(select top 1 MOUV_DATE from mouvement mv where mv.MARC_ID > m.MARC_ID order by mv.MOUV_DATE desc),
MARC_PA=(select top 1 MOUV_PA from mouvement mv where mv.MARC_ID = m.MARC_ID
order by mv.MOUV_DATE desc),
MARC_PR=(select top 1 MOUV_PR from mouvement mv where mv.MARC_ID = m.MARC_ID
order by mv.MOUV_DATE desc)
from MARCHANDISE m


Comment puis-je faire ?

Merci par avance




Avatar
jack
Merci beaucoup Fred,

C'est exactement ça.

"Fred BROUARD" wrote in message
news:%
En principe ceci devrait suffire :

SELECT MVT.*, MARC_LIBELLE
FROM mouvement AS MVT
INNER JOIN (SELECT MC.MARC_ID, MC.MARC_LIBELLE, MV.MAX_DATE
FROM marchandise AS MC
INNER JOIN (SELECT M.MARC_ID, MAX(MOUV_DATE)
AS MAX_DATE
FROM mouvement AS M
GROUP BY M.MARC_ID) AS MV
ON MC.MARC_ID = MV.MARC_ID ) AS T
ON MVT.MARC_ID = T.MARC_ID
AND MVT.MOUV_DATE = T.MAX_DATE

A +

--
Frédéric BROUARD, MVP SQL Server, expert bases de données et langage SQL
Le site sur le langage SQL et les SGBDR : http://sqlpro.developpez.com
Audit, conseil, expertise, formation, modélisation, tuning, optimisation
Enseignant aux Arts & Métiers PACA et à L'ISEN Toulon - Var Technologies
*********************** http://www.sqlspot.com *************************


jack a écrit :
> Bonjour,
>
> J'ai une table marchandise
> MARC_ID int
> MARC_LIBELLE varchar(80)
> ...
>
> Une table mouvement
>
> MOUV_ID int
> MARC_ID int
> MOUV_DATE datetime
> MOUV_PA decimal(18,2)
> MOUV_PR decimal (18,2)
> ...
>
> La table mouvement recensant tous les mouvements de la table


marchandise.
>
> J'essaie d'obtenir les dernières dates de mouvement, PA et PR pour les
> marchandises.
> Si je fais
>
> select distinct m.MARC_ID, m.MARC_LIBELLE, mv.MOUV_DATE, mv._MOUV_PA ,
> mv_MOUV_PR
> from MARCHANDISE m
> left outer join (select top 1 * from mouvement order by MOUV_DATE desc)


mv
> on m.MARC_ID=mv.MARC_ID
>
> je n'obtiens évidemment que le dernier mouvement de la table et non le
> dernier mouvement pour chaque article
>
> Si je fais left outer join (select top 1 * from mouvement where
> m1.MARC_ID=m.MARC_ID order by MOUV_DATE desc) mv
> Ca ne marche pas non plus (le deuxième m.MARC_ID est inconnu)
>
>
> Et je voudrais éviter d'avoir à faire 3 fois la même requête en mettant
> quelque chose du genre
>
> select distinct
> m.MARC_ID,m.MARC_CODETRI,m.MARC_CODEARTICLE,m.MARC_DESIGNATION,
>
> MOUV_DATE=(select top 1 MOUV_DATE from mouvement mv where mv.MARC_ID > > m.MARC_ID order by mv.MOUV_DATE desc),
> MARC_PA=(select top 1 MOUV_PA from mouvement mv where mv.MARC_ID m.MARC_ID
> order by mv.MOUV_DATE desc),
> MARC_PR=(select top 1 MOUV_PR from mouvement mv where mv.MARC_ID m.MARC_ID
> order by mv.MOUV_DATE desc)
> from MARCHANDISE m
>
>
> Comment puis-je faire ?
>
> Merci par avance
>
>




Avatar
jack
Re bonjour Fred,

La demande a évolué...

En fait il faudrait que je récupère le max(MOUV_DATE) avec MOUV_PA et
MOUV_PR tel que vous me l'avez indiqué.
Ca c'est OK.

Mais en fait il faudrait que je récupère 2 max avec PA et PR selon le type
de mouvement.

lorsque MOUV_TYPE = 1 ou 2 c'est de l'achat
lorsque MOUV_TYPE= 51c'est une vente

J'aimerais obtenir le résultat suivant

MARC_ID, MARC_LIBELLE, MAX_DATE, MOUV_PA, MOUV_PR pour MOUV_TYPE in (1,2),
MAX_DATEVENTE,MOUV_QTE pour MOUV_TYPEQ

Et tout cela en une seule requête si possible.

Suis-je clair ?

Merci par avance


"Fred BROUARD" wrote in message
news:%
En principe ceci devrait suffire :

SELECT MVT.*, MARC_LIBELLE
FROM mouvement AS MVT
INNER JOIN (SELECT MC.MARC_ID, MC.MARC_LIBELLE, MV.MAX_DATE
FROM marchandise AS MC
INNER JOIN (SELECT M.MARC_ID, MAX(MOUV_DATE)
AS MAX_DATE
FROM mouvement AS M
GROUP BY M.MARC_ID) AS MV
ON MC.MARC_ID = MV.MARC_ID ) AS T
ON MVT.MARC_ID = T.MARC_ID
AND MVT.MOUV_DATE = T.MAX_DATE

A +

--
Frédéric BROUARD, MVP SQL Server, expert bases de données et langage SQL
Le site sur le langage SQL et les SGBDR : http://sqlpro.developpez.com
Audit, conseil, expertise, formation, modélisation, tuning, optimisation
Enseignant aux Arts & Métiers PACA et à L'ISEN Toulon - Var Technologies
*********************** http://www.sqlspot.com *************************


jack a écrit :
> Bonjour,
>
> J'ai une table marchandise
> MARC_ID int
> MARC_LIBELLE varchar(80)
> ...
>
> Une table mouvement
>
> MOUV_ID int
> MARC_ID int
> MOUV_DATE datetime
> MOUV_PA decimal(18,2)
> MOUV_PR decimal (18,2)
> ...
>
> La table mouvement recensant tous les mouvements de la table


marchandise.
>
> J'essaie d'obtenir les dernières dates de mouvement, PA et PR pour les
> marchandises.
> Si je fais
>
> select distinct m.MARC_ID, m.MARC_LIBELLE, mv.MOUV_DATE, mv._MOUV_PA ,
> mv_MOUV_PR
> from MARCHANDISE m
> left outer join (select top 1 * from mouvement order by MOUV_DATE desc)


mv
> on m.MARC_ID=mv.MARC_ID
>
> je n'obtiens évidemment que le dernier mouvement de la table et non le
> dernier mouvement pour chaque article
>
> Si je fais left outer join (select top 1 * from mouvement where
> m1.MARC_ID=m.MARC_ID order by MOUV_DATE desc) mv
> Ca ne marche pas non plus (le deuxième m.MARC_ID est inconnu)
>
>
> Et je voudrais éviter d'avoir à faire 3 fois la même requête en mettant
> quelque chose du genre
>
> select distinct
> m.MARC_ID,m.MARC_CODETRI,m.MARC_CODEARTICLE,m.MARC_DESIGNATION,
>
> MOUV_DATE=(select top 1 MOUV_DATE from mouvement mv where mv.MARC_ID > > m.MARC_ID order by mv.MOUV_DATE desc),
> MARC_PA=(select top 1 MOUV_PA from mouvement mv where mv.MARC_ID m.MARC_ID
> order by mv.MOUV_DATE desc),
> MARC_PR=(select top 1 MOUV_PR from mouvement mv where mv.MARC_ID m.MARC_ID
> order by mv.MOUV_DATE desc)
> from MARCHANDISE m
>
>
> Comment puis-je faire ?
>
> Merci par avance
>
>