Альтернатива этому запросу для запуска под MariaDb 10.1 - PullRequest
0 голосов
/ 31 октября 2018

Этот запрос работает, как и ожидалось, в Mysql 8, но MariaDB 10.1 используется на моем сервере. Вы знаете, существует ли альтернатива этому? И как этого добиться?

SELECT * FROM (
SELECT
  *,
  SEC_TO_TIME(SUM(TIME_TO_SEC(TIMEDIFF(hs.`ending_hour`, hs.`starting_hour`))) OVER (ORDER BY hs.starting_hour RANGE BETWEEN INTERVAL '12' HOUR PRECEDING AND INTERVAL '12' HOUR following)) AS tot
FROM
  time_table hs
  WHERE hs.`starting_hour` > DATE_SUB(NOW(), INTERVAL 50 DAY) AND hs.`ending_hour` <= NOW()
 ORDER BY hs.`starting_hour` ASC
 ) t1
  HAVING tot >= '14:00:00' 
 ;

скрипка

Проблема в том, что RANGE BETWEEN INTERVAL в OVER оконная функция не существует в MariaDB на данный момент.

Спасибо

Пример данных:

        id  starting_hour        ending_hour          
------  -------------------  ---------------------
     1  2018-09-02 06:00:00  2018-09-02 08:30:00  
     2  2018-09-02 08:30:00  2018-09-02 10:00:00  
     4  2018-09-03 11:00:00  2018-09-03 15:00:00  
     5  2018-09-04 15:30:00  2018-09-04 16:00:00  
     6  2018-09-04 16:15:00  2018-09-04 17:00:00  
     7  2018-09-19 00:00:00  2018-09-19 03:00:00  
     8  2018-09-19 04:00:00  2018-09-19 15:00:00  
     9  2018-09-20 00:00:00  2018-09-20 22:01:00  
    10  2018-10-21 12:00:00  2018-10-21 11:00:00  
    11  2018-10-29 09:09:00  2018-10-29 10:10:00  
    12  2018-10-09 02:10:00  2018-10-09 14:00:00  

В моем примере использования идентификаторы 7, 8 и 9 являются результатами.

RE-EDIT

Благодаря ответу @Gordon Linoff, это исправленный запрос. Но, наконец, не работает, как ожидалось. Увеличение INTERVAL 50 DAY возвращает ненужные строки, которых нет в оконной функции MySQL.

SELECT hs.*,
       (
       SELECT SEC_TO_TIME(SUM(TIME_TO_SEC(TIMEDIFF(hs2.ending_hour, hs2.starting_hour))))
        FROM hours_sailor hs2
        WHERE hs2.starting_hour >= DATE_SUB(hs.starting_hour, INTERVAL 12 HOUR) AND hs2.starting_hour <= DATE_SUB(NOW(), INTERVAL 12 HOUR)
      ) AS duration
FROM `time_table` hs
WHERE hs.`starting_hour` > DATE_SUB(NOW(), INTERVAL 50 DAY) AND hs.`ending_hour` <= NOW()
HAVING duration >= '14:00:00' 
ORDER BY hs.starting_hour ASC;

1 Ответ

0 голосов
/ 31 октября 2018

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

SELECT hs.*,
       (SELECT SEC_TO_TIME(SUM(TIME_TO_SEC(TIMEDIFF(hs2.ending_hour, hs2.starting_hour)))
        FROM time_table hs2
        WHERE hs2.starting_hour >= hs.starting_hour - INTERVAL '12' HOUR AND
              hs2.starting_hour <= hs.starting_hour + INTERVAL '12' HOUR
      ) AS tot
FROM time_table hs
WHERE hs.starting_hour > DATE_SUB(NOW(), INTERVAL 50 DAY) AND
      hs.ending_hour <= NOW()
HAVING tot >= '14:00:00' 
ORDER BY hs.starting_hour ASC;

EDIT:

Если вы также хотите установить временные ограничения для расчета «диапазона», вам нужно включить его в подзапрос. Эта фильтрация встроена в оконную функцию, но это чаще помеха, чем функция:

SELECT hs.*,
       (SELECT SEC_TO_TIME(SUM(TIME_TO_SEC(TIMEDIFF(hs2.ending_hour, hs2.starting_hour)))
        FROM time_table hs2
        WHERE hs2.starting_hour >= hs.starting_hour - INTERVAL '12' HOUR AND
              hs2.starting_hour <= hs.starting_hour + INTERVAL '12' HOUR AND
              hs2.starting_hour > DATE_SUB(NOW(), INTERVAL 50 DAY) AND
              hs2.ending_hour <= NOW()
      ) AS tot
FROM time_table hs
WHERE hs.starting_hour > DATE_SUB(NOW(), INTERVAL 50 DAY) AND
      hs.ending_hour <= NOW()
HAVING tot >= '14:00:00' 
ORDER BY hs.starting_hour ASC;
...