Разрезать строку, содержащую временной диапазон, на несколько строк (сложный вопрос sql) - PullRequest
3 голосов
/ 18 апреля 2020

Прежде всего, я не смог указать заголовок, содержащий всю мою проблему. Мои извинения.

Моя цель - умножать строки при изменении некоторых значений столбцов, пока не будет достигнут определенный критерий. Да, ужасное объяснение.

У меня есть:

CREATE TABLE OldTable 
(
    fullname varchar(50) NOT NULL,
    unit varchar(50) NOT NULL,
    code int NOT NULL,
    shift_datetime datetime NOT NULL,
    timespan int NOT NULL
)

INSERT INTO OldTable (fullname, unit, code, shift_datetime, timespan) 
VALUES ('John Smith', 'Heroes', '239', '2020-03-04 13:35:00.000', '55'
'Tom Cruise', 'Heroes', '213', '2020-03-05 09:13:00.000', '8'
'My Mom', 'Heroes', '483', '2020-02-01 08:57:00.000', '16')

дает эту таблицу, OldTable:

| fullname   | unit   | code | shift_datetime          | timespan |
+------------+--------+------+-------------------------+----------+
| John Smith | Heroes | 239  | 2020-03-04 13:35:00.000 |      55  |
| Tom Cruise | Heroes | 213  | 2020-03-05 09:13:00.000 |       8  |
| Mom        | Heroes | 483  | 2020-02-01 08:57:00.000 |      16  |

Я хотел бы создать это NewTable:

| fullname   | unit   | code | shift_datetime          | timespan |
+------------+--------+------+-------------------------+----------+
| John Smith | Heroes | 239  | 2020-03-04 13:35:00.000 |      15  |
| John Smith | Heroes | 239  | 2020-03-04 13:50:00.000 |      15  |
| John Smith | Heroes | 239  | 2020-03-04 14:05:00.000 |      15  |
| John Smith | Heroes | 239  | 2020-03-04 14:20:00.000 |      10  |
| Tom Cruise | Heroes | 213  | 2020-03-05 09:13:00.000 |       8  |
| Mom        | Heroes | 483  | 2020-02-01 08:57:00.000 |      15  |
| Mom        | Heroes | 483  | 2020-02-01 08:12:00.000 |       1  |

Таким образом, формулировка задачи скорее

if span > 15, затем делится на floor(span/15) рядов с span = 15 в каждой строке, увеличивая shift_datetime на 15 минут для каждой добавленной строки, и, наконец, добавляя последняя строка, где span = span %% 15 и добавьте эти span %% 15 минуты к наибольшему значению shift_datetime в этом "l oop".

Если у вас есть идеи, как «атаковать» эту проблему, я был бы признателен. Я не только ищу решение, но я очень ищу совет о том, как справиться с такой проблемой.

Я могу сделать это в R через al oop, поэтому я предполагаю, что это может быть сделано также в al oop в SQL. Я, однако, хотел бы услышать о других вариантах или идеях.

1 Ответ

5 голосов
/ 18 апреля 2020

Похоже, что рекурсивный CTE может помочь:

with cte as (
      select fullname, unit, code, shift_datetime, 
             (case when timespan > 15 then 15 else timespan end) as timespan,
             timespan as time_remaining, 1 as lev
      from oldtable
      union all
      select fullname, unit, code,
             dateadd(minute, 15, shift_datetime),
             (case when time_remaining > 15 then 15 else time_remaining end) as timespan,
             time_remaining - 15, lev + 1
      from cte
      where time_remaining > 15
     )
select * 
from cte
order by 1, lev;

Здесь - это дб <> скрипка.

...