views:

2421

answers:

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?

+2  A: 

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.

tpdi
+1  A: 

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
A: 

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
However , unlike other answers , it is very pl/sql centric.
Learning
What PL/SQL? That's just SQL.
Jeffrey Kemp
Works for you, but not for me. With my NLS settings, days are named "MONTAG", "DIENSTAG", "MITTWOCH" etc. In other words, your solution depends on regional settings.
ammoQ
+2  A: 

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
Jeffrey Kemp