альтернатива команде lag SQL - PullRequest
2 голосов
/ 24 ноября 2010

У меня есть таблица с такой таблицей.

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

и т. Д.

Мне нужно рассчитать ожидаемые продажи для каждого месяца и тип книги на основе последних 2месяцы продаж.Таким образом, для марта и типа A это будет (100 + 50) / 2 = 75 Для марта и типа B это 120/1, поскольку данных за февраль нет.

Я пытался использовать функцию задержки, но она не сработала, поскольку в нескольких строках отсутствуют данные.

Есть идеи по этому поводу?

Ответы [ 4 ]

1 голос
/ 24 ноября 2010

Поскольку планируется игнорировать пропущенные значения, это, вероятно, должно работать. В данный момент у вас нет базы данных, чтобы протестировать ее, но утром она даст вам еще один шанс

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;

Этот тип предполагает, что месяц имеет тип данных date и может быть отсортирован по ... если это просто текстовая строка, вам понадобится что-то еще.

Обычно вы можете просто использовать rows between 2 preceding and 1 preceding, но для этого потребуется две предыдущие точки данных, а не обязательно два предыдущих месяца, если пропущены строки.

Вы могли бы решить это с задержкой, но это было бы немного сложнее.

0 голосов
/ 24 ноября 2010

Внешнее объединение разделов может помочь создать недостающие данные.Создайте набор месяцев и присоедините эти значения к каждой строке по месяцам и выполните объединение один раз для каждого типа книги.Я создал месяцы с января по апрель в этом примере:

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
0 голосов
/ 24 ноября 2010

Что-то вроде (простите за синтаксис сервера sql, но вы поняли):

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 голосов
/ 24 ноября 2010

Насколько я знаю, вы можете присвоить lag () значение по умолчанию:

  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

(Предполагая, что в столбце «Месяц» на самом деле не указаны JAN или FEB, но есть действительные, настраиваемые даты.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...