2009-04-22 14 views
4

Disons que j'ai une table, ClientTrade, comme ainsi:PLSQL: Obtenez somme pour chaque jour de la semaine et la somme totale pour la semaine en une seule requête

ClientName , TradeDate , Quantity 

Et je veux créer une requête dans Oracle PLSQL qui doit retourner le résultat comme celui-ci: (les jours sont dérivés de la colonne TradeDate et LUN. = somme (Quantité) pour lun, mar = somme (Quantité) pour mar ... etc.)

ClientName Mon Tue Wed Thu Fri Sat Sun TotalForWeek 
ABC   10 15 5 2 4 0 0 34 
XYZ   1 1 2 1 2 0 0 7 

En supposant que ce rapport aura toujours les conditions qui le font fonctionner pendant une semaine, est-ce pos sible de créer ceci dans une seule requête?

+0

Il est drôle - presque à chaque fois, les gens oublient de donner un nom à la table. 95% cohérent dans les questions SQL. –

+1

Le nom de la première table est toujours "a". ;) – tpdi

+0

OK .. c'est parti. Pas que cela fasse une grande différence à mon avis. Mais mieux vaut être dans 5% :) – Learning

Répondre

3

Sous-requêtes.

select ClientName, 
(select sum(b.quantity) 
from table b where b.clientName = a.clientname 
and b.tradedate = [some constant or calculation that identifies monday]) 
as Mon, 
(select sum(b.quantity) 
from table b where b.clientName = a.clientname 
and b.tradedate = [some constant or calculation that identifies tuesday]) 
as Tue, 

..etc.. 
from table a 

Un nettoyeur, mais peut-être moins de manière efficace implique une vue avec un groupe par: ew

create view quantityperday as 
select clientname, 
tradedate, 
dayofweek(tradedate) as dow, 
weekofyear(tradedate) as woy, 
year(tradedate) as y, 
sum(quantity) as quantity 
from table 
group by clientname, tradedate; 

Puis:

select clientname, b.quantity as Mon, c.quantity as Tue .... 
from table a join quantityperday b 
on (a.clientname = b.clientname and b.y = '2008' 
and b.doy = 2 and b.dow = 'Monday') 
quantityperday c 
on (a.clientname = c.clientname and c.y = '2008' 
and c.doy = 2 and c.dow = 'Tuesday') 
join .... 

La raison pour laquelle cela devient laid est que nous sommes lignes pivotantes en colonnes.

2

Voyons voir:

SELECT Client, MonSum, TueSum, WedSum, ThuSum, FriSum, SatSum, SunSum, TotSum 
    FROM (SELECT ClientName AS Client, SUM(Quantity) AS MonSum 
      FROM Trades 
      WHERE DayOfWeek(TradeDate) = 'Monday' 
       AND TradeDate BETWEEN DATE '..Monday..' AND DATE '..Sunday..' 
      GROUP BY ClientName 
     ) AS MonData 
     JOIN 
     (SELECT ClientName AS Client, SUM(Quantity) AS TueSum ... 
     ) AS TueData ON Mondata.Client = TueData.Client 
     JOIN 
     ... 
     (SELECT ClientName AS Client, SUM(Quantity) AS TotSum 
      FROM Trades 
      WHERE TradeDate BETWEEN DATE '..Monday..' AND DATE '..Sunday..' 
      GROUP BY ClientName 
     ) AS TotData ON MonData.Client = TotData.Client 
    ORDER BY Client; 

pas bien rangé, mais comme @tpdi mentionné dans sa réponse, c'est parce que nous sommes des lignes pivotant en colonnes. J'ai utilisé la clause cohérente TradeDate BETWEEN ... pour couvrir la semaine en question.

0

Merci pour vos réponses. En fait, j'ai trouvé quelque chose dans plsql qui fonctionne bien:

select clientname, 
max(decode(trim(dow),'MONDAY',totalquantity,0)) Mon, 
max(decode(trim(dow),'TUESDAY',totalquantity,0)) Tue, 
max(decode(trim(dow),'WEDNESDAY',totalquantity,0)) Wed, 
max(decode(trim(dow),'THURSDAY',totalquantity,0)) Thu, 
max(decode(trim(dow),'FRIDAY',totalquantity,0)) Fri, 
(
max(decode(trim(dow),'MONDAY',totalquantity,0)) + 
max(decode(trim(dow),'TUESDAY',totalquantity,0)) + 
max(decode(trim(dow),'WEDNESDAY',totalquantity,0)) + 
max(decode(trim(dow),'THURSDAY',totalquantity,0)) + 
max(decode(trim(dow),'FRIDAY',totalquantity,0)) 
) TOTAL 
from 
(
    select clientname, 
    to_char(tradedate, 'DAY') as dow, 
    sum(quantity) as totalquantity 
    from ClientTrade a 
    where a.tradedate >= trunc(sysdate-7,'D') 
    and a.tradedate <= trunc(sysdate-7,'D') + 4 
    group by c.clientshortname, tradedate 
) 
group by clientname 
+0

Cependant, contrairement à d'autres réponses, il est très pl/sql centré. – Learning

+0

Quel PL/SQL? C'est juste SQL. –

+2

Fonctionne pour vous, mais pas pour moi. Avec mes paramètres NLS, les jours sont nommés "MONTAG", "DIENSTAG", "MITTWOCH", etc. En d'autres termes, votre solution dépend des paramètres régionaux. –

6

Il suffit de simplifier un peu ...

SELECT ClientName, 
     SUM(CASE WHEN to_char(TradeDate,'DY')='MON' THEN Quantity ELSE NULL END) AS Mon, 
     SUM(CASE WHEN to_char(TradeDate,'DY')='TUE' THEN Quantity ELSE NULL END) AS Tue, 
     SUM(CASE WHEN to_char(TradeDate,'DY')='WED' THEN Quantity ELSE NULL END) AS Wed, 
     SUM(CASE WHEN to_char(TradeDate,'DY')='THU' THEN Quantity ELSE NULL END) AS Thu, 
     SUM(CASE WHEN to_char(TradeDate,'DY')='FRI' THEN Quantity ELSE NULL END) AS Fri, 
     SUM(CASE WHEN to_char(TradeDate,'DY')='SAT' THEN Quantity ELSE NULL END) AS Sat, 
     SUM(CASE WHEN to_char(TradeDate,'DY')='SUN' THEN Quantity ELSE NULL END) AS Sun, 
     SUM(Quantity) AS TotalForWeek 
FROM ClientTrade 
GROUP BY ClientName 
0

Mon essai sur Oracle 11G:

select clientname, nvl(MON,0) MON, nvl(TUE,0) TUE, nvl(WED,0) WED, nvl(THU,0) THU, nvl(FRI,0) FRI, nvl(SAT,0) SAT, nvl(SUN,0) SUN, 
nvl(MON,0) + nvl(TUE,0) + nvl(WED,0) + nvl(THU,0) + nvl(FRI,0) +nvl(SAT,0) + nvl(SUN,0) TotalForWeek 
from 
(
select clientname,to_char(tradedate,'Dy') dw, sum(quantity) quantity from ClientTrade 
group by clientname, to_char(tradedate,'Dy') 
) 
pivot (sum(quantity) FOR dw in ('Mon' as MON,'Tue' as TUE,'Wed' AS WED,'Thu' AS THU,'Fri' AS FRI,'Sat' AS SAT,'Sun' AS SUN)) 
Questions connexes