Kri*_*Jr. 3 sql sql-server split loops
首先,我无法指定包含整个问题的标题。我很抱歉。
我的目标是在更改某些列值的同时乘以行,直到满足某个标准。是的,糟糕的解释。
我有:
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')
Run Code Online (Sandbox Code Playgroud)
产生这个表,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 |
Run Code Online (Sandbox Code Playgroud)
我想创建这个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 |
Run Code Online (Sandbox Code Playgroud)
所以问题的表述是
if span > 15,然后在每行中分成floor(span/15)几行,span = 15同时shift_datetime为每个添加的行增加15 分钟,最后添加最后一行 wherespan = span %% 15并将这些span %% 15分钟添加到该shift_datetime“循环”中的最大值。
如果您对如何“解决”这个问题有任何想法,我将不胜感激。我不仅在寻找解决方案,而且非常在寻找有关如何处理此类问题的建议。
我可以通过循环在 R 中做到这一点,所以我假设这也可以通过 SQL 中的循环来完成。但是,我很想听听其他选择或想法。
听起来递归 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;
Run Code Online (Sandbox Code Playgroud)
这是一个 db<>fiddle。