MySQL: добавление столбца к запросу, который суммирует последовательные данные из другой таблицы - PullRequest
1 голос
/ 21 апреля 2020

У меня есть две таблицы. Таблица 1 представляет собой список товаров и идентификаторов, а таблица 2 представляет собой список данных о продажах, где в каждой строке показаны продажи определенного элемента c для конкретной недели c:

Таблица 1: Элементы

ITEM NAME        ITEM ID  
Item1  item1_id  
Item2   item2_id  
Item3   item3_id  
....

и

Таблица 2: Данные о продажах

ITEM  WEEK  SALES  
Item1 1 3  
Item1 2 5  
Item1 3 4  
Item2 2 5  
Item2 3 6  
....

Я хочу создать в своем выходном столбце, который документирует количество недель последовательных продаж (NUM_Sales). Результат для этого примера будет

ITEM NAME ITEM ID NUM_Sales  
Item1 item1_id 3  
Item2 item2_id 2

Поскольку у Item1 продажи в неделях 1,2,3 (таким образом, 3 последовательные недели), в то время как у Item2 продажи только в неделях 2,3 (таким образом, 2 последовательные недели)

Я очень новичок в MySQL, поэтому никогда не делал ничего такого сложного и не уверен, с чего начать. Как я могу написать запрос для этого?

Ответы [ 2 ]

1 голос
/ 21 апреля 2020

Если вы используете MySQL 8.0, вы можете решить эту проблему с помощью оконных функций. Идея состоит в том, чтобы использовать разницу между row_number() и week для создания групп смежных записей:

alter table items add column num_sales int;

update items i
inner join (
    select item, max(cnt) cnt
    from (
        select s.*, count(*) over(partition by item, week - rn) cnt
        from (
            select 
                s.*, 
                row_number() over(partition by item order by week) rn
                from sales_data s
        ) s
    ) s
    group by item
) s on s.item = i.item
set i.num_sales = s.cnt
0 голосов
/ 21 апреля 2020

Вы можете рассчитать первую неделю в последней последовательности как:

select s.item_id,
       max(s.week) as last_week,
       max(case when sprev.week is null then week end) as first_week,
       (max(s.week) - max(case when sprev.week is null then week end) + 1) as num_weeks
from sales s left join
     sales sprev
     on sprev.item_id = s.item_id and sprev.week = s.week
group by s.item_id;

Вы можете включить это в update как:

update items i join
       (select s.item_id,
               max(s.week) as last_week,
               max(case when sprev.week is null then week end) as first_week,
               (max(s.week) - max(case when sprev.week is null then week end) + 1) as num_weeks
        from sales s left join
             sales sprev
             on sprev.item_id = s.item_id and sprev.week = s.week
        group by s.item_id
       ) iw
       on iw.item_id = i.item_id
    set num_sales = iw.num_weeks;

Это немного более кратко в MySQL 8+ - использование lag() вместо самостоятельного соединения. При правильном индексировании - sales(item_id, week) - производительность при этом может быть даже выше, чем у оконной функции.

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