Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
2826 connectés 

 


 Mot :   Pseudo :  
 
 Page :   1  2
Page Suivante
Auteur Sujet :

[SGBD] Encore une requête à décorner les boeufs...

n°1297608
Arjuna
Aircraft Ident.: F-MBSD
Posté le 02-02-2006 à 17:06:02  profilanswer
 

Reprise du message précédent :
Une petite question bête : est-ce que vous savez pourquoi quand je lance une requête avec TOAD, ce dernier occupe 100% du CPU durant toute la requête :??:
 
Genre on dirait que c'est lui qui execute la requête !

mood
Publicité
Posté le 02-02-2006 à 17:06:02  profilanswer
 

n°1297620
Beegee
Posté le 02-02-2006 à 17:15:35  profilanswer
 

Je suis pas réveillé non plus j'avais même pas regardé les index de msk ... je regardais ceux de pro :D
 
M'enfin faut dire que c'est tellement peu lisible ;)
 
Ce qui pourrait être intéressant, c'est de couper la dernière requête que je t'ai passée, et de créer des tables temporaires contenant les résultats intermédiaires. Dans certains cas on peut y gagner.
Surtout si tu veux le résultat pour tous les produits ...

n°1297633
infoman64
JE SUIS LA POUR TOI MON AMI
Posté le 02-02-2006 à 17:30:13  profilanswer
 

Je crois qu'on peut lui decerner la palme de la plus grande requete

n°1297667
Arjuna
Aircraft Ident.: F-MBSD
Posté le 02-02-2006 à 18:00:43  profilanswer
 

infoman64 a écrit :

Je crois qu'on peut lui decerner la palme de la plus grande requete


bah j'ai déjà fait très largement pire (mais alors largement de chez largement :D)
 
J'aime bien faire des requêtes de 10 Ko :D
 
(curieusement, sur celles-là, j'ai très rarement de problème de perf :pt1cable:)
 
Pis quand j'en ai, j'ose pas demander, parceque vu la tronche du bidule, c'est à coup faire planter le forum de peur :D


Message édité par Arjuna le 02-02-2006 à 18:00:56
n°1297682
orafrance
Posté le 02-02-2006 à 18:19:11  profilanswer
 

la fonction analytique LEAD devrait faire l'affaire alors, elle permet de récupérer la ligne précédente dans les lignes fetchées... avec un order by bien senti ça devrait le faire.
 
Je suis désolé j'ai vraiment pas le temps mais si tu peux me faire un modéle simple avec un échantillon de données, je pourrais peut-être te pondre un début d'idée ;)

n°1297697
orafrance
Posté le 02-02-2006 à 18:33:59  profilanswer
 

Je me lance mais comme je comprends rien ça risque de merder... mais ça te donnera peut-être des idées ;)
 

Code :
  1. SELECT '1' ord, pro.sigfou, msk.sigdep, pro.codpro, pro.codblocage, 0 entrees,
  2.        0 sorties, 0 initinventaire, msk.c01 avantinv,nummsk
  3.   FROM msk, pro
  4. WHERE pro.codsoc = 2
  5.    AND pro.sigfou = 'HERITAGE'
  6.    AND msk.codsoc = pro.codsoc
  7.    AND msk.codpro = pro.codpro
  8.    AND msk.sigdep = pro.sigdep
  9.    AND msk.numlot = ' '
  10.    AND msk.nummsk =
  11.           (SELECT MAX (m1.nummsk)
  12.              FROM msk m1
  13.             WHERE m1.codsoc = msk.codsoc
  14.               AND m1.codpro = msk.codpro
  15.               AND m1.sigdep = msk.sigdep
  16.               AND m1.numlot = ' '
  17.               AND m1.nummsk <
  18.                      (SELECT MAX (m2.nummsk)
  19.                         FROM msk m2
  20.                        WHERE m2.codsoc = m1.codsoc
  21.                          AND m2.codpro = m1.codpro
  22.                          AND m2.sigdep = m1.sigdep
  23.                          AND m2.datmvt BETWEEN '20051231' AND '20060131'
  24.                          AND m2.codosk = 'INICPT')
  25.      )


 
Devient :
 

Code :
  1. SELECT * FROM
  2. (
  3. SELECT '1' ord, pro.sigfou, msk.sigdep, pro.codpro, pro.codblocage, 0 entrees,
  4.        0 sorties, 0 initinventaire, msk.c01 avantinv,nummsk
  5.   FROM msk, pro
  6. WHERE pro.codsoc = 2
  7.    AND pro.sigfou = 'HERITAGE'
  8.    AND msk.codsoc = pro.codsoc
  9.    AND msk.codpro = pro.codpro
  10.    AND msk.sigdep = pro.sigdep
  11.    AND msk.numlot = ' '
  12. ORDER BY nummsk desc
  13. ) m1
  14. WHERE nummsk <
  15.                      (SELECT MAX (m2.nummsk)
  16.                         FROM msk m2
  17.                        WHERE m2.codsoc = m1.codsoc
  18.                          AND m2.codpro = m1.codpro
  19.                          AND m2.sigdep = m1.sigdep
  20.                          AND m2.datmvt BETWEEN '20051231' AND '20060131'
  21.                          AND m2.codosk = 'INICPT')
  22. AND ROWNUM = 1


     
Si je comprends bien, tu veux pas le max, mais celui juste avant... alors :
 

Code :
  1. SELECT *
  2. (
  3. SELECT *,rownum rang FROM
  4.  (
  5.  SELECT '1' ord, pro.sigfou, msk.sigdep, pro.codpro, pro.codblocage, 0 entrees,
  6.         0 sorties, 0 initinventaire, msk.c01 avantinv,nummsk
  7.    FROM msk, pro
  8.   WHERE pro.codsoc = 2
  9.     AND pro.sigfou = 'HERITAGE'
  10.     AND msk.codsoc = pro.codsoc
  11.     AND msk.codpro = pro.codpro
  12.     AND msk.sigdep = pro.sigdep
  13.     AND msk.numlot = ' '
  14.        AND datmvt BETWEEN '20051231' AND '20060131'
  15.         AND codosk = 'INICPT'
  16.  ORDER BY nummsk desc
  17.  )
  18. )
  19. WHERE rang = 2;


 
Ca s'approche pas de ce que tu voudrais ?
 
Avec la fonction RANK tu peux faire plus joli encore ;)

n°1297771
Arjuna
Aircraft Ident.: F-MBSD
Posté le 02-02-2006 à 19:38:22  profilanswer
 

Pour la première requête :
-> Nan, ma requête n'est pas intuitive. Elle ne retourne pas UNE ligne, mais autant de lignes qu'il y a de produits différents attachés au fournisseur. Le coup du ROWNUM ne peut donc pas marcher dans mon cas.
 
Pour ta seconde requête :
-> Non plus ;) Là tu vas me retourner le résultat de l'éventuel avant dernier inventaire dans l'inteval de dates. Moi je veux le dernier mouvement (codosk != 'INICPT') avant le dernier inventaire (codosk = 'INTCPT')
 
Donc ça marche pas non plus :spamafote:

n°1297786
Arjuna
Aircraft Ident.: F-MBSD
Posté le 02-02-2006 à 19:51:50  profilanswer
 

Je suis en train de me demander par contre...
 
NUMMSK du dernier inventaire :
 

Code :
  1. select max(nummsk), codsoc, sigdep, codpro, numlot
  2. from msk
  3. where codosk = 'INICPT'
  4. and datmvt between '20051231' and '20060131'
  5. group by codsoc, sigdep, codpro
  6. -- Aliasé "m2" dans la requête suivante


 
Je veux le MAX() du NUMMSK parmis les NUMMSK inférieurs à cette valeur pour chaque produit :
 

Code :
  1. select max(m1.nummsk), m1.codsoc, m1.sigdep, m1.codpro, m1.numlot
  2. from (...) m2, msk m1
  3. where m2.codsoc = m1.codsoc
  4. and m2.sigdep = m1.sigdep
  5. and m2.codpro = m1.codpro
  6. and m2.numlot = m1.numlot
  7. and m1.codosk != 'INICPT'
  8. and m1.nummsk < m2.nummsk
  9. group by m1.codsoc, m1.sigdep, m1.codpro, m1.numlot
  10. -- Aliasé "m4" dans la requête suivante


 
Et je veux récupérer les infos de la ligne qui correspond à ce max pour chaque produit :
 

Code :
  1. select m3.c01
  2. from (...) m4, msk m3, pro
  3. where m4.codsoc = m3.codsoc
  4. and m4.sigfou = m3.sigfou
  5. and m4.sigdep = m3.sigdep
  6. and m4.codpro = m3.codpro
  7. and m4.numlot = m4.numlot
  8. and m3.codsoc = pro.codsoc
  9. and m3.sigdep = pro.sigdep
  10. and m3.codpro = pro.codpro
  11. and pro.codsoc = 2
  12. and pro.sigfou = 'HERITAGE'


 
A priori, à un ou deux détails près, c'est la réécriture de ma première requête en mode peut-être plus compréhensible...
 
Vais tester ce que ça donne. Mais je doute fortement que ça change grand chose à la vitesse d'execution, les sous-requêtes sont les mêmes, on les fait juste pas au même moment... :/


Message édité par Arjuna le 02-02-2006 à 19:52:05
n°1298064
Arjuna
Aircraft Ident.: F-MBSD
Posté le 02-02-2006 à 20:11:51  profilanswer
 

Merdoum ! Je viens de perdre un gros post avec une énorme requête :sweat:

n°1298083
Arjuna
Aircraft Ident.: F-MBSD
Posté le 02-02-2006 à 20:24:51  profilanswer
 

Alors... Ma requête (après quelques nouvelles corrections - passé de 26 secondes à 13 secondes -) :
 

Code :
  1. select pro.sigfou, pro.sigdep, pro.codpro, pro.codblocage, pro.datmar, pro.nompro, 0 entrees, 0 sorties, 0 initinventaire, msk.c01 avantinv, 0 variationinv
  2. from msk, pro
  3. where pro.codsoc = 2
  4. and pro.sigfou = 'HERITAGE'
  5. and msk.codsoc = pro.codsoc
  6. and msk.codpro = pro.codpro
  7. and msk.sigdep = pro.sigdep
  8. and msk.numlot = ' '
  9. and msk.nummsk =
  10. (
  11. select max(m1.nummsk)
  12. from msk m1
  13. where m1.codsoc = msk.codsoc
  14. and m1.codpro = msk.codpro
  15. and m1.sigdep = msk.sigdep
  16. and m1.numlot = msk.numlot
  17. and m1.codosk != 'INICPT'
  18. and m1.nummsk <
  19. (
  20.  select max(m2.nummsk)
  21.  from msk m2
  22.  where m2.codsoc = m1.codsoc
  23.  and m2.codpro = m1.codpro
  24.  and m2.sigdep = m1.sigdep
  25.  and m2.datmvt between '20051231' and '20060131'
  26.  and m2.codosk = 'INICPT'
  27.  and m2.numlot = m1.numlot
  28. )
  29. )


 
13 secondes - 96 lignes
 
La nouvelle requête (après quelques corrections aussi) :
 

Code :
  1. select pro.sigfou, pro.sigdep, pro.codpro, pro.codblocage, pro.datmar, pro.nompro, 0 entrees, 0 sorties, 0 initinventaire, m3.c01 avantinv, 0 variationinv
  2. from
  3. (
  4. select max(m1.nummsk) nummsk, m1.codsoc, m1.sigdep, m1.codpro, m1.numlot
  5. from
  6. (
  7.  select max(nummsk) nummsk, codsoc, sigdep, codpro, numlot
  8.  from msk
  9.  where codosk = 'INICPT'
  10.  and datmvt between '20051231' and '20060131'
  11.  group by codsoc, sigdep, codpro, numlot
  12. ) m2, msk m1
  13. where m2.codsoc = m1.codsoc
  14. and m2.sigdep = m1.sigdep
  15. and m2.codpro = m1.codpro
  16. and m2.numlot = m1.numlot
  17. and m1.codosk != 'INICPT'
  18. and m1.nummsk < m2.nummsk
  19. group by m1.codsoc, m1.sigdep, m1.codpro, m1.numlot
  20. ) m4, msk m3, pro
  21. where m4.codsoc = m3.codsoc
  22. and m4.sigdep = m3.sigdep
  23. and m4.codpro = m3.codpro
  24. and m4.numlot = m3.numlot
  25. and m4.nummsk = m3.nummsk
  26. and m3.codsoc = pro.codsoc
  27. and m3.sigdep = pro.sigdep
  28. and m3.codpro = pro.codpro
  29. and m3.numlot = ' '
  30. and pro.codsoc = 2
  31. and pro.sigfou = 'HERITAGE'


 
4 minutes et 29 secondes / 96 lignes
C'est le même résultat.
 
Visiblement, à moins que je ne me soit planté quelque part, les sous-select dans le FROM sont foutus en table temporaire avant, ce qui prends beaucoup de temps car il ne sont presque pas filtrés.
 
M'enfin ça vous permettra peut-être de mieu comprendre ce que fait la requête...

Message cité 1 fois
Message édité par Arjuna le 02-02-2006 à 20:26:01
mood
Publicité
Posté le 02-02-2006 à 20:24:51  profilanswer
 

n°1298093
Arjuna
Aircraft Ident.: F-MBSD
Posté le 02-02-2006 à 20:33:44  profilanswer
 

J'ai beau la tourner dans tous les sens, j'arrive pas à voir une solution pour l'écrire autrement... :sweat:

n°1298298
orafrance
Posté le 03-02-2006 à 09:35:34  profilanswer
 

c'est mieux... maintenant tu introduits les fonctions analytiques pour remplacer le ROWNUM par ton besoin : http://lalystar.developpez.com/fon [...] ques/#L3.8
 
Et ça devrait le faire :)

n°1298322
Arjuna
Aircraft Ident.: F-MBSD
Posté le 03-02-2006 à 09:59:12  profilanswer
 

ça moi je veux bien mais :
- je vois toujours pas comment ça peut m'aider
- et j'ai pas de rownum dans mes requêtes :o
 
pendant un moment je me suis dit "mais oui, c'est sa requête que je dois étudier". saufqu'après l'avoir charcutée un peu, je me suis rendu compte de ce que j'ai répondu hier : l'est complètement à côté de la plaque ta requête, au mieu je récupère l'inventaire de n'année d'avant ;)

n°1298334
Beegee
Posté le 03-02-2006 à 10:08:49  profilanswer
 

Ce sont des tables très souvent mises à jour ?
 
Tu pourrais peut-être préparer des données dans une vue matérialisée  ...
 
Sinon des fonctions analytiques bien écrites comme proposait orafrance, mais je suis pas un expert dans ce domaine :)

n°1298349
orafrance
Posté le 03-02-2006 à 10:23:19  profilanswer
 

j'arrive pas à comprendre le besoin fonctionnel donc je peux pas aider mieux désolé :/

n°1298357
Beegee
Posté le 03-02-2006 à 10:30:16  profilanswer
 

Arjuna a écrit :


La nouvelle requête (après quelques corrections aussi) :
 

Code :
  1. select pro.sigfou, pro.sigdep, pro.codpro, pro.codblocage, pro.datmar, pro.nompro, 0 entrees, 0 sorties, 0 initinventaire, m3.c01 avantinv, 0 variationinv
  2. from
  3. (
  4. select max(m1.nummsk) nummsk, m1.codsoc, m1.sigdep, m1.codpro, m1.numlot
  5. from
  6. (
  7.  select max(nummsk) nummsk, codsoc, sigdep, codpro, numlot
  8.  from msk
  9.  where codosk = 'INICPT'
  10.  and datmvt between '20051231' and '20060131'
  11.  group by codsoc, sigdep, codpro, numlot
  12. ) m2, msk m1
  13. where m2.codsoc = m1.codsoc
  14. and m2.sigdep = m1.sigdep
  15. and m2.codpro = m1.codpro
  16. and m2.numlot = m1.numlot
  17. and m1.codosk != 'INICPT'
  18. and m1.nummsk < m2.nummsk
  19. group by m1.codsoc, m1.sigdep, m1.codpro, m1.numlot
  20. ) m4, msk m3, pro
  21. where m4.codsoc = m3.codsoc
  22. and m4.sigdep = m3.sigdep
  23. and m4.codpro = m3.codpro
  24. and m4.numlot = m3.numlot
  25. and m4.nummsk = m3.nummsk
  26. and m3.codsoc = pro.codsoc
  27. and m3.sigdep = pro.sigdep
  28. and m3.codpro = pro.codpro
  29. and m3.numlot = ' '
  30. and pro.codsoc = 2
  31. and pro.sigfou = 'HERITAGE'


 
4 minutes et 29 secondes / 96 lignes


 
Explain Plan :
 
SELECT STATEMENT Hint=RULE                                  
  FILTER                                  
    SORT GROUP BY                                  
      TABLE ACCESS BY INDEX ROWID MSK                                
        NESTED LOOPS                                  
          NESTED LOOPS                                  
            NESTED LOOPS                                  
              VIEW                                  
                SORT GROUP BY                                  
                  TABLE ACCESS FULL MSK                                
              TABLE ACCESS BY INDEX ROWID PRO                                
                INDEX RANGE SCAN WI_PRO                                
            TABLE ACCESS BY INDEX ROWID MSK                                
              INDEX RANGE SCAN MSK_IDX1                                
          INDEX RANGE SCAN MSK_IDX1                                

n°1298807
Arjuna
Aircraft Ident.: F-MBSD
Posté le 03-02-2006 à 19:14:59  profilanswer
 

Beegee a écrit :

Ce sont des tables très souvent mises à jour ?
 
Tu pourrais peut-être préparer des données dans une vue matérialisée  ...
 
Sinon des fonctions analytiques bien écrites comme proposait orafrance, mais je suis pas un expert dans ce domaine :)


Impossible de faire une vue matérialisée : la table MVT est mise à jour en permanance, à la fois "à la volée" par les fonctions utilisateurs et par lot la nuit lors de batchs.
 
En effet, c'est la table des mouvements de stocks.
 
Sauf que c'est un ERP. Et les stocks ça se limite pas à un stock physique dans un unique dépôt.
 
Y'a 16 compteurs en tout (ici, seuls les 9 premiers sont paramétrés).
On y trouve notamment :
- Stock physique
- Préparation (ce qui est dans le physique, en cours de prépération pour l'envois)
- Réservation (ce qui n'est pas dans le physique, mais qui a été vendu - attente d'approvisionnement)
- Les réceptions (ce qui n'est pas encore dans le physique, mais matériellement au dépôt - en cours de comptage et validatio qualité -)
- Les approvisionnement (les commandes d'approvisionnement)
Plus des calculés :
- Disponible à la vente (physique - prépa)
- A terme (physique - prépa - résa + réception + appro)
- Ventes (prepa + résa)
- Achats (réceptions + appro)
 
Et ce pour 9 dépôts différents.
 
Donc à chaque fois qu'une commande d'achat ou de vente est saisie, on met à jours des compteurs. Idem pour les factures, les bons de livraisons, etc.
Sans parler des transferts, les retours SAV, etc.
 
Vu qu'ici c'est une centrale d'une chaîne de magasins, tu imagines bien que les gens passent leur temps à saisir ce genre d'infos. C'est pas par hasard si en janvier (mois très calme, car les magasins ont déjà leurs stocks constitués avant noël, et c'est prériode de soldes puis inventaire, donc appro interdite) y'a eu près de 30 000 nouvelles lignes dans la table.
 
Donc la vue matérialisée est à abandonner. La vue tout court, why not, mais ça devrait pas changer grand chose.
 
Sinon, pour les fonctions analytiques, je suis à fond partant, mais avec un exemple qui marche. Jusqu'à présent, la doc que j'ai lu ou les tentatives d'orafrance n'entre jamais dans le cadre de mon besoin...


Message édité par Arjuna le 03-02-2006 à 19:30:10
n°1298816
Arjuna
Aircraft Ident.: F-MBSD
Posté le 03-02-2006 à 19:27:20  profilanswer
 

orafrance a écrit :

j'arrive pas à comprendre le besoin fonctionnel donc je peux pas aider mieux désolé :/


Ben le fonctionnel, je l'ai expliqué :o
 
Début janvier, il y a eu un inventaire. (première vague de saisie 'INICPT' le 2 janvier, puis saisie des variations d'inventaire 'INVV' dans la semaine qui suivait (recomptage et correction).
 
On me demande, pour chaque produit -ici je me suis limité aux produits d'un fournisseur- :
1/ Le cumul des entrées saisies depuis l'inventaire
2/ Le cumul des sorties saisies depuis l'inventaire
3/ La quantité inventoriée
4/ Le cumul des quantités rcomptées
5/ L'état des stocks avant l'inventaire
 
Afin de refaire un inventaire et valider que le premier était juste (je but de ce second inventaire n'est pas d'inventorier, mais de faire sauter des têtes en montrant qu'il y a eu des erreurs d'inventaire).
J'ai aucun scrupule à faire cette requête, car les quelques erreurs qu'on a vu passer, ce sont des erreurs ponctuelles et indépendantes de l'inventaire (valorisation des stocks en se basant sur un prix exprimé dans une unité différente que cette de stockage). Pis de toute façon je suis pas là pour prendre position dans les questions politiques de la société ;)
Enfin voilà, ça explique pourquoi ces chiffres qui, il est vrai, ont à la base, un intérêt plus que limité.
 
Pour les 1, 2, 3 et 4, aucun souci, c'est le reste de ma requête énorme, et ça tourne en moins d'une seconde.
 
L'état des stocks avant inventaire (uniquement le compteur physique, qui est C01 de la table MSK) est retrouvé comme suit :
-> Dans la période de dates, on recherche le plus grand numéro de mouvement (NUMMSK) dont l'oppération est une initialisation du compteur physique (codosk = 'INICPT'). Ca correspond à la saisie du résultat d'inventaire.
-> On recherche, parmi les NUMMSK plus petits que ce numéro d'inventaire, le plus grand qui correspond au même produit dans le même dépôt (y'a pas de gestion de lots ni d'emplacements ici, donc on peut en faire abstraction)
-> On récupère le C01 de cette ligne, c'est l'état du stock physique avant inventaire.
 
Donc, ma requête est bien (pseudo SQL)
 
select c01 from msk where nummsk = (select max(nummsk) from msk where nummsk < (select max(numsk) from msk where codosk = 'INICPT' and datmsk between ...))
 
(avec les jointures qui vont bien sur la société, le produit et le dépot)
 
Je pense que c'est plus clair comme ça ;)


Message édité par Arjuna le 03-02-2006 à 19:32:13
n°1298818
Arjuna
Aircraft Ident.: F-MBSD
Posté le 03-02-2006 à 19:34:01  profilanswer
 

PS: et ma requête ne retourne pas UNE ligne, mais une ligne pour chaque produit (à condition qu'il y ait un iventaire ce de produit dans la prériode, sinon ça retourne rien ;))

n°1299637
orafrance
Posté le 06-02-2006 à 10:36:08  profilanswer
 

et en PL/SQL ce serait pas plus simple ? :ange:

mood
Publicité
Posté le   profilanswer
 

 Page :   1  2
Page Suivante

Aller à :
Ajouter une réponse
 

Sujets relatifs
[SGBD] Oracle 8i, TextSearch : besoin d'infosErreur SQL 1064 : Requête imbriquée avec jointure !!!
[Résolu]Requete soustractive MySQL ?Mesurer le temps d'exécution d'une requête XQuery
modifier le contenu d'une requête sélection stockée sous Acessproblème requête client vers servlet
requete+champ+count[Mysql] 1 Grosse requete OU plusieurs petite ?
demande d'aide REQUETE COMPLEXErequête sql : pas d'affichage
Plus de sujets relatifs à : [SGBD] Encore une requête à décorner les boeufs...


Copyright © 1997-2025 Groupe LDLC (Signaler un contenu illicite / Données personnelles)