sqlplus : problème union 1 to many avec dates

sqlplus : problème union 1 to many avec dates - SQL/NoSQL - Programmation

Marsh Posté le 08-11-2005 à 12:41:30    

'jour,
 
Un problème qui me pose souci depuis longtemps.
Je dois faire une union de 2 queries qui permettent de récupérer des valeurs (nombres) et des dates.
J'ai un problème de 'format type' sur les dates, genre :
 
select sum(A), sum(B), D1, D2 from
(select a.somme1 A, 0 B, b.date1 D1, b.date2 D2 from table a, table b
where ....
union
select 0 A, b.somme, 0 D1, 0 D2
where ....)
group by ...
 
Bon, c'est pas très bien expliqué, mais vous devinez le problème : l'union sur le nombre fonctionne mais pas sur la date (ni les strings d'ailleurs), du moins je ne sais pas comment remplacer la date dans le 2nd query comme je le fais pour le nombre (somme A <-> 0 A)
 
Si quelqu'un a une soluce : thanks  :jap:

Reply

Marsh Posté le 08-11-2005 à 12:41:30   

Reply

Marsh Posté le 08-11-2005 à 13:26:36    

Avec quelle base de données ?
 
Si c'est Oracle, il faudrait faire

select sum(A), sum(B), D1, D2
   from  
(select a.somme1 A, 0 B, b.date1 D1, b.date2 D2
   from table a, table b  
  where ....  
union  
 select 0 A, b.somme B, to_date('01/01/1900', 'dd/mm/yyyy') D1,
    to_date('01/01/1900', 'dd/mm/yyyy') D2  
 where ....)  
group by ...

Reply

Marsh Posté le 08-11-2005 à 13:58:39    

Argh, c'est sûrement ça ! Je teste dès que j'ai résolu mon petti souci sur l'union et le plantage qui va avec :sarcastic:  
Merci  :jap:

Reply

Marsh Posté le 08-11-2005 à 19:37:06    

faut pas mettre 0 mais null, j'ai fais ce genre de requete la semaine passée et ça ne m'a vraiment pas posé de probleme

Reply

Marsh Posté le 09-11-2005 à 10:24:25    

Salut,
Je suis sous Oracle (8.1.7) j'ai toujours eu des soucis en utilisant NULL.
Dans mon exemple, tu ferais quoi ?
Par ailleurs, le to_date ne fait pas exactement ce que j'attends ...
Je précise que le b.date1 D1 et b.date2 D2 sont mis dans un decode :  
decode(b.produit, 'blabla',b.date1) D1, etc ...

Reply

Marsh Posté le 10-11-2005 à 11:17:38    

Donne toute la requête et on verra ce qui cloche ...

Reply

Marsh Posté le 10-11-2005 à 17:43:39    

Bon, là j'ai essayé des trucs, qui ne marchent pas, mais la base c'est ça :
 

Code :
  1. select  article ARTICLE, name NAME, descr DESCR, max(be) BE, max(nl) NL, max(fr) FR, sum(stock) STOCK, sum(purch) PURCH, sum(sales) SALES from
  2. (select a.article article, a.name name, a.descr descr, decode(a.ctry,' 01',a.date) be, decode(a.ctry,' 21',a.date) nl, decode(a.ctry,' 31',a.date) fr, b.stock stock, b.purch purch, b.sales sales from  table_a a, table_b b
  3. where a.article = b.article
  4. UNION ALL
  5. select a.article article, a.name name, a.descr descr, to_date(19000101,'yyyymmdd') be, to_date(19000101,'yyyymmdd') nl, to_date(19000101,'yyyymmdd') fr, 0 stock, 0 purch, 0 sales from  table_a a, table_b b
  6. where a.article = b.article) c
  7. where substr(c.article,10,12) between '200' and '399'
  8. or substr(c.article,10,12) between '500' and '599'
  9. group by c.article, c.name, c.descr, c.be, c.nl, c.fr
  10. order by 1 asc

Reply

Marsh Posté le 10-11-2005 à 18:02:59    

Voici ta requête, en plus lisible :
 

Code :
  1. SELECT article ARTICLE,
  2.        name NAME,
  3.        descr DESCR,
  4.        max(be) BE,
  5.        max(nl) NL,
  6.        max(fr) FR,
  7.        sum(stock) STOCK,
  8.        sum(purch) PURCH,
  9.        sum(sales) SALES
  10. FROM (SELECT a.article article,
  11.              a.name name,
  12.              a.descr descr,
  13.              decode(a.ctry,' 01',a.date) be,
  14.              decode(a.ctry,' 21',a.date) nl,
  15.              decode(a.ctry,' 31',a.date) fr,
  16.              b.stock stock,
  17.              b.purch purch,
  18.              b.sales sales
  19.       FROM table_a a, table_b b
  20.       WHERE a.article = b.article
  21.       UNION ALL
  22.       SELECT a.article article,
  23.              a.name name,
  24.              a.descr descr,
  25.              to_date(19000101,'yyyymmdd') be,
  26.              to_date(19000101,'yyyymmdd') nl,
  27.              to_date(19000101,'yyyymmdd') fr,
  28.              0 stock,
  29.              0 purch,
  30.              0 sales
  31.       FROM table_a a, table_b b
  32.       WHERE a.article = b.article) c
  33. WHERE SUBSTR(c.article, 10, 12) BETWEEN '200' AND '399'
  34. OR SUBSTR(c.article, 10, 12) BETWEEN '500' AND '599'
  35. GROUP BY c.article, c.name, c.descr, c.be, c.nl, c.fr
  36. ORDER BY 1 ASC;


 
Quelques commentaires :
- Pas besoin de donner un nom aux champs déjà nommés comme il faut ...
- Les DECODE s'utilisent généralement avec un argument supplémentaires : DECODE(a, b, c, d) signifie : si a = b alors c sinon d. Dans ton cas tu utilises seulement 3 arguments, par conséquent, je ne sais pas trop ce que Oracle choisit pour d !
- Tu fais des to_date en passant des nombres (19000101) au lieu de chaînes de caractères ('19000101') !
 
Donc voici la requête légèrement corrigée / simplifiée :
 

Code :
  1. SELECT article,
  2.        name,
  3.        descr,
  4.        max(be) BE,
  5.        max(nl) NL,
  6.        max(fr) FR,
  7.        sum(stock) STOCK,
  8.        sum(purch) PURCH,
  9.        sum(sales) SALES
  10. FROM (SELECT a.article,
  11.              a.name,
  12.              a.descr,
  13.              decode(a.ctry,' 01',a.date, ???) be,
  14.              decode(a.ctry,' 21',a.date, ???) nl,
  15.              decode(a.ctry,' 31',a.date, ???) fr,
  16.              b.stock,
  17.              b.purch,
  18.              b.sales
  19.       FROM table_a a, table_b b
  20.       WHERE a.article = b.article
  21.       UNION ALL
  22.       SELECT a.article,
  23.              a.name,
  24.              a.descr,
  25.              to_date('19000101','yyyymmdd') be,
  26.              to_date('19000101','yyyymmdd') nl,
  27.              to_date('19000101','yyyymmdd') fr,
  28.              0 stock,
  29.              0 purch,
  30.              0 sales
  31.       FROM table_a a, table_b b
  32.       WHERE a.article = b.article) c
  33. WHERE SUBSTR(c.article, 10, 12) BETWEEN '200' AND '399'
  34. OR SUBSTR(c.article, 10, 12) BETWEEN '500' AND '599'
  35. GROUP BY c.article, c.name, c.descr, c.be, c.nl, c.fr
  36. ORDER BY 1 ASC;


 
A toi de voir maintenant avec quoi remplacer les ??? ;)

Reply

Marsh Posté le 10-11-2005 à 21:19:31    

Etrange, je pensais que l'absence d'alias posait problème entre le query et le sous-query => select article from (select a.article) ?
Pour info les to_date (20050101,'yyyymmdd') fonctionnent très bien. Je doute que l'année 1900 nécessite forcément d'utiliser un string ...
Quant au decode, je l'utilise comme ça dans bien des query : il implique que si c'est ' 01' on affiche la date liée, sinon rien, si ' 21' la date liée, sion rien ... Je n'ai jamais eu à me plaindre de ce fonctionnement, et les utilisateus non plus ... Note que ici le cas est différent de ce que je fais d'habitude, donc en effet je vais voir pour mettre un truc à la place des ??? ;)
 
Mon souci vient des dates. Car comme tu le vois, avec les stock, purch, sales, pas de problème car ce sont des nombres (stock <-> 0 stock, ... L'union se fait bien et c'est le même datatype).
En gros, le résultat que je devrais avoir serait par exemple :
 
12345 TOTO PELUCHE 01/10/2004 [BLANC OU 0 si pas de date liée à NL] 22/06/2004 200 0 50
 
Pour chaque article, donc une ligne par article ... Et là je coince à cause des dates :/


Message édité par Mosca le 10-11-2005 à 21:22:08
Reply

Marsh Posté le 10-11-2005 à 21:24:19    

Tu peux donner le résultat, montrer ce qui va pas ?
Et lancer la requête interne (celle avec l'union), et nous donner les résultats également.
(lance celle que j'ai écrite en mettant NULL au lieu des ???)

Reply

Marsh Posté le 10-11-2005 à 21:24:19   

Reply

Marsh Posté le 10-11-2005 à 23:04:41    

Le query :

Code :
  1. SELECT item ITEM,
  2.             seac PROD,
  3.             seak DESCR,
  4.             max(be) BE,
  5.             max(nl) NL,
  6.             max(fr) FR,
  7.             sum(stock) STOCK,
  8.             sum(ordr) ORDR,
  9.             sum(alloc) ALLOC
  10.      FROM (SELECT a.t$item item,
  11.                   a.t$seac seac,
  12.                   a.t$seak seak,
  13.                   decode(a.t$ctry,' 01',a.t$date, NULL) be,
  14.                   decode(a.t$ctry,' 21',a.t$date, NULL) nl,
  15.                   decode(a.t$ctry,' 31',a.t$date, NULL) fr,
  16.                   b.t$stoc stock,
  17.                   b.t$ordr ordr,
  18.                   b.t$allo alloc
  19.            FROM ttable100100 a, ttdinv001100 b
  20.            WHERE a.t$item = b.t$item 
  21.    and a.t$ctry in (' 01', ' 21', ' 31')
  22.    and b.t$cwar = '101'
  23.            UNION ALL 
  24.            SELECT a.t$item item,
  25.                   a.t$seac seac,
  26.                   a.t$seak seak,
  27.                   to_date('19000101','yyyymmdd') be,
  28.                   to_date('19000101','yyyymmdd') nl,
  29.                   to_date('19000101','yyyymmdd') fr,
  30.                   0 stock,
  31.                   0 ordr,
  32.                   0 alloc
  33.            FROM ttable100100 a, ttdinv001100 b 
  34.            WHERE a.t$item = b.t$item
  35.    and a.t$ctry in (' 01', ' 21', ' 31')
  36.    and b.t$cwar = '101') c
  37.      WHERE SUBSTR(c.item, 10, 12) BETWEEN '200' AND '399' 
  38.      OR SUBSTR(c.item, 10, 12) BETWEEN '500' AND '599' 
  39.      GROUP BY c.item, c.seac, c.seak, c.be, c.nl, c.fr 
  40.      ORDER BY 1 ASC;


 
Le résultat (données changées pour raison confidentielle  :sarcastic: ), mais les dates sont inchangées :
 
123466789012 blablablabla blablablablabla    01/01/99                          177          0          0
 
123466789012 blablablabla blablablablabla    01/01/00 01/01/00 01/01/00          0          0          0
 
123466789012 blablablabla blablablablabla             01/01/99                 177          0          0
 
123466789012 blablablabla blablablablabla                      01/01/99        177          0          0
 
On a quatre records : il en faudrait un seul
le 2ème correspondrait, mais il manque le stock (qui est de 177) et la date est incorrecte (ne correspond à rien, même pas à NULL)
On a 4 records parcequ'il y a 4 pays liés au même article et aucun n'a de date commercialisation (NULL <-> 01/01/99)
Or je veux afficher pour chaque article la date de commercialisation qui correspond au pays auquel il est lié (ou aucune date), et pour 3 pays seulement, pas plus !
Je crois que je devrais faire une seconde union pour la date ... Là c'est un 1 to many, mais en fait c'est un 1 to many - to many
 
(pareil avec null ou sans null)


Message édité par Mosca le 10-11-2005 à 23:11:18
Reply

Marsh Posté le 11-11-2005 à 00:21:46    

Je comprends déjà pas pourquoi Oracle te laisse faire un GROUP BY sur des champs qui sont le résultat de SUM et MAX ...
 
Logiquement, tu ne devrais faire le group by que sur c.item, c.seac, c.seak !

Reply

Marsh Posté le 11-11-2005 à 10:56:19    

Ouais, il me laisse le faire, c'est vrai que j'ai oublié d'enlever le group by sur ces champs ...
J'ai d'ailleurs noté de drôles de trucs parfois : dans certains query, si j'oublie d'indiquer la jointure sur un seul champ (t$date au lieu de a.t$date par exemple) le query passe quand même ...

Reply

Marsh Posté le 11-11-2005 à 11:12:39    

Quand il n'y a pas d'ambiguïté, il n'y a pas besoin de préfixer (mais c'est mieux car plus lisible).

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed