Значение следующей строки без оконных функций - PullRequest
0 голосов
/ 25 января 2019

У меня есть следующая таблица обновлений статусов страниц. Каждая строка имеет статус изменения:

CREATE TABLE `t1` (
  `page_id` int(11) NOT NULL,
  `country` varchar(2) COLLATE utf8mb4_unicode_ci NOT NULL,
  `status` varchar(45) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `date` datetime DEFAULT NULL,
  PRIMARY KEY (`page_id`,`country`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

INSERT INTO t1        (page_id, country, status, date) 
VALUES                (1, 'de', 'deactivated', '2018-09-28 14:52:11' ) ,
                      (1, 'de', 'activated', '2018-09-28 14:54:18' ) ,
                      (1, 'de', 'deactivated', '2018-09-28 14:60:12' ) ,
                      (1, 'de', 'moderated', '2018-09-28 14:54:12' ) ,
                      (2, 'es', 'deactivated', '2018-09-28 14:52:01' ) ,
                      (2, 'es', 'activated', '2018-09-28 14:52:07' ) ,
                      (2, 'es', 'deactivated', '2018-09-28 14:52:11' ) 

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

CREATE TABLE `t2` (
  `page_id` int(11) NOT NULL,
  `country` varchar(2) COLLATE utf8mb4_unicode_ci NOT NULL,
  `status` varchar(45) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `date_from` datetime DEFAULT NULL,
  `date_to` datetime DEFAULT NULL,
  PRIMARY KEY (`page_id`,`country`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;



INSERT INTO t2        (page_id, country, status, date_from, date_to) 
VALUES                (1, 'de', 'deactivated', '2018-09-28 14:52:11', '2018-09-28 14:54:12'  ) ,
                      (1, 'de', 'moderated', '2018-09-28 14:54:12', '2018-09-28 14:54:18'  ) ,
                      (1, 'de', 'activated', '2018-09-28 14:54:18','2018-09-28 14:60:12'  ) ,
                      (1, 'de', 'deactivated', '2018-09-28 14:60:12','2018-01-25 14:60:12' ) ,
                      (2, 'es', 'deactivated', '2018-09-28 14:52:01','2018-09-28 14:52:07'  ) ,
                      (2, 'es', 'activated', '2018-09-28 14:52:07', '2018-09-28 14:52:11' ) ,
                      (2, 'es', 'deactivated', '2018-09-28 14:52:11','2018-01-25 14:52:11'  ) ;

Проблема в том, что мы все еще используем MySQL 5.7 и не обновились до mysql8 с функциями cte и window, что легко решило бы проблему:

  SELECT
         country,
         page_id,
         status,
         date as date_from,
        COALESCE(MIN(date) OVER(PARTITION BY country, page_id ORDER BY date DESC
                            ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING),
                        TIMESTAMPADD(day, 1, current_timestamp())) as date_to
  FROM t1 ;

Я предполагаю, что должен быть трюк с самостоятельным соединением, но не могу понять, как именно!

1 Ответ

0 голосов
/ 25 января 2019

В MySQL 8+ вы обычно используете для этого LEAD(), а не свое сложное выражение.

В более ранних версиях вы можете использовать коррелированный подзапрос:

select t1.*,
       (select tt1.date
        from t1 tt1
        where tt1.country = t1.country and tt1.page_id = t1.page_id and
              tt1.date > t1.date 
        order by tt1.date asc
        limit 1
       ) as date_to
from t1;

Используется NULL для значений date_to в конце каждой последовательности. Это имеет больше смысла для меня.

Если вы хотите повторить date_from вместо этого (что я не рекомендую), то вы можете сделать:

select t1.*,
       (select min(tt1.date_from, t1.date_from)
        from t1 tt1
        where tt1.page_id = t1.page_id and
              tt1.date_from > t1.date_from
       ) as date_to
from t1;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...