Как найти пробелы в дате одной и той же группы данных - mySQL

0

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

id       promotion_name  period      value
8495115  Cash_Discount1  2016-11-01  10.00
8495116  Cash_Discount1  2016-12-01  20.00
8491724  Cash_Discount1  2017-01-01  10.00
8479109  Cash_Discount1  2017-02-01  20.00
8459125  Cash_Discount1  2017-03-01  40.00
8491649  Cash_Discount1  2017-06-01  30.00
8491648  Cash_Discount1  2017-07-01  50.00
8491647  Cash_Discount1  2017-08-01  70.00
8491646  Cash_Discount1  2017-09-01  80.00

Период в приведенной выше таблице обозначает дату начала выполнения акции, и она работает в течение месяца. Следовательно, первый ряд означает, что скидка наличных средств колеблется от 1-11-2016 до 30-11-2016.

Мне нужны те же данные в приведенном ниже формате.

promotion_name start_date  end_date    value
Cash_Discount1  2016-11-01  2017-03-31  100.00
Cash_Discount1  2017-06-01  2017-09-30  230.00

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

я пробовал использовать это для начинающих, но я нигде не близок к результату.

SELECT p.id
     , p.promotion_name
     , p.period AS start_date
     , q.period AS end_date
     , p.value AS spend
  FROM table p 
  LEFT 
  JOIN table q 
    ON p.id = q.id 
   AND p.promotion_name = q.promotion_name
   AND p.period = DATE_SUB(q.period,INTERVAL 1 MONTH)

Я в ситуации, когда я не знаю, что искать.

Любая помощь приветствуется.

  • 1
    Что такое Cash_Discount? Очень трудно понять связь между набором данных и набором результатов.
  • 0
    @Strawberry: Cash_discount в наборе данных и наборе результатов одинаковы. я редактировал вопрос. если в периодах есть промежуток, необходимо заполнить новую строку.
Показать ещё 5 комментариев
Теги:
gaps-and-islands

1 ответ

0
Лучший ответ
select
  ts.promotion_name,
  min(t.period) as date_start,
  max(t.period) as date_end,
  sum(t.value)  as spend
from mytable ts
left join mytable t1
  on  t1.promotion_name = ts.promotion_name
  and t1.period = ts.period - interval 1 month
join mytable t
  on  t.promotion_name = ts.promotion_name
  and t.period >= ts.period
  and t.period <= (
    select min(t2.period)
    from mytable t2
    left join mytable t3
      on  t3.promotion_name = t2.promotion_name
      and t3.period = t2.period + interval 1 month
    where t2.promotion_name = ts.promotion_name
      and t2.period >= ts.period
      and t3.period is null
  )
where ts.promotion_name = 'Cash_Discount1'
  and t1.period is null
group by ts.id
order by date_start

Демо: https://www.db-fiddle.com/f/7Xx5bSQmRUGzUCLyB4rKBf/1

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

select ts.*
from mytable ts
left join mytable t1
  on  t1.promotion_name = ts.promotion_name
  and t1.period = ts.period - interval 1 month
where ts.promotion_name = 'Cash_Discount1'
  and t1.period is null

Демо: https://www.db-fiddle.com/f/fKaNQPkgZqbTfY3Je6Kz4/0

и получить последнюю дату группы с подзапросом

select min(t2.period)
from mytable t2
left join mytable t3
  on  t3.promotion_name = t2.promotion_name
  and t3.period = t2.period + interval 1 month
where t2.promotion_name = ts.promotion_name
  and t2.period >= ts.period
  and t3.period is null

Демо: https://www.db-fiddle.com/f/hSNZwjDuL1nf2NzPoms5JG/0

Тогда вам нужно другое соединение с условием диапазона

  and t.period >= ts.period    -- start_date
  and t.period <= (<subquery>) -- end_date

и использовать агрегацию над соответствующими строками.

  • 0
    Спасибо @paul, Это очень помогает.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню