2009-04-22 6 views
4

Допустим, у меня есть таблица, ClientTrade, как таким образом:PLSQL: Получить сумму на каждый день недели и общая сумма за неделю в одном запросе

ClientName , TradeDate , Quantity 

И я хочу, чтобы создать запрос в Oracle PLSQL, который должен возвращать результат следующим образом: (дни получены из колонки TradeDate и Пнд = сумма (количество) пн, вт = сумма (количество) вт ... и т.д.)

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 

Предполагая, что этот отчет всегда будет иметь условия, в которых он будет работать в течение одной недели, Чтобы создать это в одном запросе?

+0

Это смешно - почти каждый раз люди забывают дать название таблицы. 95% соответствует вопросам SQL. –

+1

Имя первой таблицы всегда «а». ;) – tpdi

+0

OK .. здесь вы идете. Не то, чтобы это имело большое значение для моего мнения. Но лучше быть в 5% :) – Learning

ответ

3

Подзапросы.

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 

уборщик, но, возможно, менее эффективный способ включает в себя представление с группой по: РЭБ

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; 

Тогда:

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

Причиной этого становится уродливым является то, что мы поворот строк в столбцы.

2

Давайте посмотрим:

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; 

Не аккуратным, но, как @tpdi отметил в своем ответе, что это потому, что мы поворотными строк в столбцы. Я использовал согласованное предложение TradeDate BETWEEN ..., чтобы охватить соответствующую неделю.

0

Спасибо за ваши ответы. На самом деле, я нашел что-то в PLSQL, который работает хорошо:

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

Однако, в отличие от других ответов, это очень pl/sql-ориентированный. – Learning

+0

Что такое PL/SQL? Это просто SQL. –

+2

Работает для вас, но не для меня. С моими настройками NLS дни называются «MONTAG», «DIENSTAG», «MITTWOCH» и т. Д. Другими словами, ваше решение зависит от региональных настроек. –

6

Просто упрощающее немного ...

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

Моя попытка на 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))