У меня есть файл CSV с четырьмя столбцами: дата, оптовый продавец, продукт и продажи.

Я ищу среднее значение продаж за последние 52 недели для каждой комбинации продукта и оптовика на каждую дату. Это означает, каковы были средние предыдущие продажи продукта A у оптовика B в момент времени C за последние 52 недели.

Например, мы знаем, что продажи продукта «А» у оптовика «Б» в январе, апреле, мае, августе составляют 100, 200, 300, 400 соответственно. Предположим, у нас нет никаких записей до января. Таким образом, среднее значение предыдущей продажи продукта «А» оптовому торговцу «В» в апреле равно 100/1, а в мае равно (200 + 100) / 2 и в августе (300 + 200 + 100) / 3.

Следующая таблица показывает мои данные:

date    wholesaler product  sales
12/31/2012  53929  UPE54     4
12/31/2012  13131  UPE55     1
2/23/2013   13131  UPE55  1156
4/24/2013   13131  UPE55     1
12/1/2013   83389  UPE54     9
12/17/2013  83389  UPE54     1
12/18/2013  52237  UPE54     9
12/19/2013  53929  UME24     1
12/31/2013  82204  UPE55     9
12/31/2013  11209  UME24     4
12/31/2013  52237  UPE54     1

Теперь я использую код Python, который правильно работает только с небольшими базами данных. Поскольку в моем наборе данных более 25 миллионов строк, я ищу лучший способ найти решение. Большое спасибо за вашу помощь!

2
Ashkan Mirzaee 5 Май 2016 в 08:09

2 ответа

Лучший ответ

Я думаю, это то, что вы ищете.

WITH    cte_prep
          AS (
               SELECT
                    YEAR(date) * 100 + DATEPART(WEEK, [DATE]) AS week
                ,   date
                ,   RANK() OVER ( PARTITION BY product, wholesaler ORDER BY YEAR(date) * 100 + DATEPART(WEEK, [DATE]) ) AS product_wholesaler_week_rank
                ,   [wholesaler]
                ,   [product]
                ,   [sales]
                FROM
                    [meta].[dbo].[sales]
             )
    SELECT
            CW.wholesaler
        ,   CW.product
        ,   CW.week
        ,   CW.product_wholesaler_week_rank
        ,   CW.sales
        ,   AVG(BW.sales) AS avg_sales
        FROM
            cte_prep AS CW
        INNER JOIN cte_prep BW
        ON  BW.product = CW.product AND
            BW.wholesaler = CW.wholesaler AND
            CW.product_wholesaler_week_rank >= BW.product_wholesaler_week_rank
            AND BW.product_wholesaler_week_rank >= CW.product_wholesaler_week_rank - 52
        GROUP BY
            CW.wholesaler
        ,   CW.product
        ,   CW.week
        , CW.sales
        ,   CW.product_wholesaler_week_rank
        ORDER BY
            CW.wholesaler
        ,   CW.product
        ,   CW.week desc

Результаты выглядят так

1
Steve de Peijper 5 Май 2016 в 06:40
select sum('sales')/count('sales') 
from table 
Group by year(date)

То, о чем вы просите, немного сложнее, чем ответ, который я дал. Я дал ответ, который работает, если вы хотите сгруппировать периоды продолжительностью в год только с 1 января по 31 декабря. Возможно, вам нужны периоды продолжительностью в год, но, возможно, вы захотите их с 1 июля по 30 июня.

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

https://dba.stackexchange.com/questions/59356/grouping-by-date-range-in-a-column

Группа SQL по диапазону дат

Как в SQL можно «группировать по» по диапазонам?

1
Community 23 Май 2017 в 12:02