SQL - нормализация временных меток к рабочим часам - PullRequest
1 голос
/ 17 сентября 2009

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

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

Что должно произойти, так это то, что даты меняются так, чтобы в субботу 14:00 стало 9:00 утра понедельника (первое допустимое время рабочей недели). 7 вечера в среду становится 9 утра четверга. и т. д. и т. д. Давайте игнорировать праздники.

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

mysql> select mydate from mytable ORDER by mydate;
+---------------------+
| mydate              |
+---------------------+
| 2009-09-13 17:03:09 | 
| 2009-09-14 09:45:49 | 
| 2009-09-15 09:57:28 | 
| 2009-09-16 21:55:01 | 
+---------------------+
4 rows in set (0.00 sec)

Первое свидание - воскресенье, поэтому оно должно быть нормализовано до 2009-09-14 09:00:00

Второе свидание в порядке, оно в 9 утра в понедельник.

Третье свидание в порядке, во вторник 9:00.

Четвертая дата - в 21:00 (в нерабочее время с 9:00 до 18:00) в среду и должна быть преобразована в 9:00 утра четверга.

Ответы [ 3 ]

1 голос
/ 17 сентября 2009

Я думаю, вам лучше с вашим Python-решением ... но мне нравятся проблемы:)

select mydate
     , case dayadjust
-- BUG
--         when 0 then mydate
-- BUG
           when 0 then case
                 when hour(mydate)<9
                       then date_add(from_days(to_days(mydate)),
                               INTERVAL 9 HOUR)
                 else mydate
           end
-- BUG SQUASHED
           else date_add(from_days(to_days(mydate) + dayadjust),
                         INTERVAL 9 HOUR)
       end as mynewdate
from (
        select mydate
             , case
                   when addday>=moreday then addday
                   else moreday
               end as dayadjust
        from (
                select mydate
                     , weekday(mydate) as w
                     , hour(mydate) as h
                     , case weekday(mydate)
                           when 6 then 1
                           when 5 then 2
                           when 4 then
                                   case
                                         when hour(mydate) >= 18 then 3
                                         else 0
                                   end
                           else 0
                       end as addday
                     , case when hour(mydate)>=18 then 1 else 0 end as moreday
                from mytable
                order by mydate
        ) alias1
) alias2

Проверено на MySQL

$ mysql tmp < phil.sql
mydate  mynewdate
2009-09-12 17:03:09     2009-09-14 09:00:00
2009-09-12 21:03:09     2009-09-14 09:00:00
2009-09-13 17:03:09     2009-09-14 09:00:00
2009-09-14 09:45:49     2009-09-14 09:45:49
2009-09-15 09:57:28     2009-09-15 09:57:28
2009-09-16 21:55:01     2009-09-17 09:00:00
2009-09-17 11:03:09     2009-09-17 11:03:09
2009-09-17 22:03:09     2009-09-18 09:00:00
2009-09-18 12:03:09     2009-09-18 12:03:09
2009-09-18 19:03:09     2009-09-21 09:00:00
2009-09-19 06:03:09     2009-09-21 09:00:00
2009-09-19 16:03:09     2009-09-21 09:00:00
2009-09-19 19:03:09     2009-09-21 09:00:00
0 голосов
/ 17 сентября 2009

Я не думаю, что вы можете сделать это одним запросом, но вы можете попробовать это:

-- Mon-Thu, after 17:00
-- Set date = next day, 9:00
UPDATE 
    myTable 
SET  
    mydate = DATE_ADD(DATE_ADD(DATE(date), INTERVAL 1 DAY), INTERVAL 9 HOUR) 
WHERE 
    TIME(mydate) >= 17 
    AND DAYOFWEEK(mydate) IN (1,2,3,4)

-- Mon-Fri, before 9:00
-- Set date = the same day, 9:00
UPDATE 
    myTable 
SET 
    mydate = DATE_ADD(DATE(date), INTERVAL 9 HOUR) 
WHERE 
    TIME(mydate) < 9 
    AND DAYOFWEEK(mydate) IN (1,2,3,4,5)

-- Fri, after 17:00, Sat, Sun
-- Set date = monday, 9.00
UPDATE 
    myTable 
SET 
    mydate = DATE_ADD(DATE_ADD(DATE(date), INTERVAL 3 DAY), INTERVAL 9 HOUR) 
WHERE 
    (TIME(mydate) >= 17 
    AND DAYOFWEEK(mydate) = 5) 
    OR DAYOFWEEK(mydate) IN (6,7)
0 голосов
/ 17 сентября 2009

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

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