Исключение строк из AGG () OVER (ROWS МЕЖДУ x PRECEDING), если они связаны с текущей строкой? - PullRequest
0 голосов
/ 25 сентября 2018

Я рассчитываю скользящее среднее из последних 100 продаж определенного товара.Я хотел бы знать, потратил ли пользователь X более 5 раз на всех остальных, на этот товар в последнем окне продаж 100.

--how much has the current row user spent on this item over the last 100 sales?
SUM(saleprice) OVER(PARTITION BY item, user ORDER BY saledate ROWS BETWEEN 100 PRECEDING AND CURRENT ROW)

--pseudocode: how much has everyone else, excluding this user, spent on that item over the last 100 sales?
SUM(saleprice) OVER(PARTITION BY item ORDER BY saledate ROWS BETWEEN 100 PRECEDING AND CURRENT ROW WHERE preceding_row.user <> current_row.ruser)

В конечном счете, я не хочу, чтобы покупки, сделанные моимбольшой спонсор, который будет учитываться в общих расходах маленьких спонсоров.Есть ли метод, который может исключать строки из окна, если они не соответствуют некоторым критериям сравнения с текущей строкой?(в моем случае не суммируйте стоимость продажи из предыдущей строки, если в ней указан тот же пользователь, что и в текущей строке)

1 Ответ

0 голосов
/ 25 сентября 2018

Этот первый выглядит хорошо для меня, если не считать 101 продаж. (100 перед И текущая строка)

--how much has the current row user spent on this item over the last 100 sales?

SUM(saleprice)
  OVER (
    PARTITION BY item, user
        ORDER BY saledate
    ROWS BETWEEN 100 PRECEDING AND 1 PRECEDING   -- 100 excluding this sale
    ROWS BETWEEN  99 PRECEDING AND CURRENT ROW   -- 100 including this sale
  )

(просто используйте один из двух предложенных ROWS BETWEEN предложений)

Во втором выражении нельзя добавить предложение WHERE.Вы можете изменить агрегацию, раздел и сортировку, но я не понимаю, как это вам поможет.Я думаю, что вам нужен коррелированный подзапрос и / или использование OUTER APPLY ...

SELECT
  *,
  SUM(saleprice)
    OVER (
      PARTITION BY item, user
          ORDER BY saledate
      ROWS BETWEEN  99 PRECEDING AND CURRENT ROW   -- 100 including this sale
    )
      AS user_total_100_purchases_to_date,
  others_sales_top_100_total.sale_price
FROM
  sales_data
OUTER APPLY
(
  SELECT
    SUM(saleprice)  AS saleprice
  FROM
  (
    SELECT TOP(100) saleprice
      FROM sales_data       others_sales
     WHERE others_sales.user     <> sales_data.user
       AND others_sales.item      = sales_data.item
       AND others_sales.saledate <= sales_data.saledate
  ORDER BY others_sales.saledate DESC
  )
    AS others_sales_top_100
)
  AS others_sales_top_100_total

РЕДАКТИРОВАТЬ: Еще один способ взглянуть на это, чтобы привести вещи в соответствие

SELECT
  *,
  usr_last100_saletotal,
  all_last100_saletotal,
  CASE WHEN usr_last100_saletotal > all_last100_saletotal * 0.8
       THEN 'user spent 80%, or more, of last 100 sales'
       ELSE 'user spent under 80% of last 100 sales'
  END
      AS 
FROM
  sales_data
OUTER APPLY
(
  SELECT
    SUM(CASE top100.user WHEN sales_data.user THEN top100.saleprice END)   AS usr_last100_saletotal,
    SUM(                                           top100.saleprice    )   AS all_last100_saletotal
  FROM
  (
    SELECT TOP(100) user, saleprice
      FROM sales_data       AS others_sales
     WHERE others_sales.item      = sales_data.item
       AND others_sales.saledate <= sales_data.saledate
  ORDER BY others_sales.saledate DESC
  )
    AS top100
)
  AS top100_summary

...