2010-11-23 8 views
2

Ich habe eine Tabelle, die eine Tabelle wie folgt hat.Alternative zu Lag SQL-Befehl

Month-----Book_Type-----sold_in_Dollars 
Jan----------A------------ 100 
Jan----------B------------ 120 
Feb----------A------------ 50 
Mar----------A------------ 60 
Mar----------B------------ 30 

und so weiter

Ich habe den erwarteten Umsatz für jeden Monat und Buchtyp auf dem letzten 2 Monate Umsatz zu berechnen. Also für März und Typ A wäre es (100 + 50)/2 = 75 Für März und Typ B ist es 120/1, da keine Daten für Feb ist da.

Ich habe versucht, die Verzögerungsfunktion zu verwenden, aber es würde nicht funktionieren, da in einigen Zeilen Daten fehlen.

Irgendwelche Ideen dazu?

Antwort

0

Soweit ich weiß, können Sie einen Standardwert geben hinken(): (. Unter der Annahme, Monat Spalte nicht wirklich enthalten JAN oder Februar aber real, bestellbaren Daten)

SELECT Book_Type, 
     (lag(sold_in_Dollars, 1, 0) OVER(PARTITION BY Book_Type ORDER BY Month) + lag(sold_in_Dollars, 2, 0) OVER(PARTITION BY Book_Type ORDER BY Month))/2 AS expected_sales 
    FROM your_table 
GROUP BY Book_Type 

0

Was ist so etwas wie (verzeihen Sie den sQL Server-Syntax, aber Sie bekommen die Idee):

Select Book_type, AVG(sold_in_dollars) 
from MyTable 
where Month in (Month(DATEADD('mm'-1,GETDATE)),Month(DATEADD('mm'-2,GETDATE))) 
group by booktype 
+0

Er will 120/1, nicht (120 + 0)/2, was albern ist. – milan

+0

Schließen Sie die Werte an und führen Sie sie aus. – SteveCav

+0

Soweit ich weiß, ignoriert Durchschnitt Nullen, also, wenn Sie über zwei Zeilen Durchschnitt und einer der Werte ist Null, dann wird nur durch 1 geteilt. –

1

Da es fehlende Werte ignorieren will, ist dies wahrscheinlich funktionieren sollte. Sie haben noch keine Datenbank testen zur Zeit auf, sondern geben es eine andere gehen am Morgen

select 
    month, 
    book_type, 
    sold_in_dollars, 
    avg(sold_in_dollars) over (partition by book_type order by month 
    range between interval '2' month preceding and interval '1' month preceding) as avg_sales 
from myTable; 

Diese Art der davon ausgeht, dass Monat ein Datum Datentyp hat und sortiert werden können ... wenn es nur eine Textzeichenfolge benötigen Sie etwas anderes.

Normalerweise können Sie einfach rows between 2 preceding and 1 preceding verwenden, aber dies wird die zwei vorherigen Datenpunkte und nicht unbedingt die zwei vorherigen Monate, wenn Zeilen fehlen.

Sie könnten es mit Verzögerung ausarbeiten, aber es wäre ein bisschen komplizierter.

+0

+1 - Ich denke, es sollte nach Monat und dann book_type partitioniert werden. Nur eine Meinung ... – Art

0

Ein externer Partitions-Join kann helfen, die fehlenden Daten zu erstellen. Erstellen Sie eine Reihe von Monaten und fügen Sie diese Werte für jede Zeile nach Monat hinzu, und führen Sie die Verknüpfung für jeden Buchtyp einmal durch. Ich habe die Monate Januar bis April in diesem Beispiel:

with test_data as 
(
    select to_date('01-JAN-2010', 'DD-MON-YYYY') month, 'A' book_type, 100 sold_in_dollars from dual union all 
    select to_date('01-JAN-2010', 'DD-MON-YYYY') month, 'B' book_type, 120 sold_in_dollars from dual union all 
    select to_date('01-FEB-2010', 'DD-MON-YYYY') month, 'A' book_type, 50 sold_in_dollars from dual union all 
    select to_date('01-MAR-2010', 'DD-MON-YYYY') month, 'A' book_type, 60 sold_in_dollars from dual union all 
    select to_date('01-MAR-2010', 'DD-MON-YYYY') month, 'B' book_type, 30 sold_in_dollars from dual 
) 
select book_type, month, sold_in_dollars 
    ,case when denominator = 0 then 'N/A' else to_char(numerator/denominator) end expected_sales 
from 
(
    select test_data.book_type, all_months.month, sold_in_dollars 
    ,count(sold_in_dollars) over 
     (partition by book_type order by all_months.month rows between 2 preceding and 1 preceding) denominator 
    ,sum(sold_in_dollars) over 
     (partition by book_type order by all_months.month rows between 2 preceding and 1 preceding) numerator 
    from 
    (
     select add_months(to_date('01-JAN-2010', 'DD-MON-YYYY'), level-1) month from dual connect by level <= 4 
    ) all_months 
    left outer join test_data partition by (test_data.book_type) on all_months.month = test_data.month 
) 
order by book_type, month