4

Let's say , I have a table, ClientTrade, like thus :

ClientName , TradeDate , Quantity

And I want to create a query in Oracle PLSQL which should return the result like this : (The days are derived from the TradeDate column and Mon = sum(Quantity) for Mon , Tue = sum(Quantity) for Tue ... 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 

Assuming that this report will always have where conditions which make it run for one week , is this possible to create this in a single query?

OMG Ponies
  • 325,700
  • 82
  • 523
  • 502
Learning
  • 8,029
  • 3
  • 35
  • 46

5 Answers5

6

Just simplifying a bit...

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
DrXCheng
  • 3,992
  • 11
  • 49
  • 72
Jeffrey Kemp
  • 59,135
  • 14
  • 106
  • 158
3

Subqueries.

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

A cleaner, but possibly less efficient way involves a view with a group by: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;

Then:

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

The reason this gets ugly is that we're pivoting rows into columns.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
tpdi
  • 34,554
  • 11
  • 80
  • 120
2

Let's see:

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;

Not tidy, but as @tpdi mentioned in his answer, that's because we're pivoting rows into columns. I've used the consistent TradeDate BETWEEN ... clause to cover the relevant week.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
0

Thanks for your answers. Actually, I found something in plsql which works out nicely :

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
Learning
  • 8,029
  • 3
  • 35
  • 46
0

My try on 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) )   
WaldiMen
  • 347
  • 2
  • 12