Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/73.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 在表中展开多个时间序列_Sql_Sql Server_Time Series - Fatal编程技术网

Sql 在表中展开多个时间序列

Sql 在表中展开多个时间序列,sql,sql-server,time-series,Sql,Sql Server,Time Series,我有一个包含多个时间序列的表,每个时间序列都与给定的ID相关联 像这样的 +--------------------------------------+ | ID | start | end | value | +--------------------------------------+ | a | 01/01/2018 | 03/01/2018 | 5 | | a | 03/01/2018 | 04/01/2018 | 6 | | a | 0

我有一个包含多个时间序列的表,每个时间序列都与给定的ID相关联

像这样的

+--------------------------------------+
| ID | start      | end        | value |
+--------------------------------------+
| a  | 01/01/2018 | 03/01/2018 | 5     |
| a  | 03/01/2018 | 04/01/2018 | 6     |
| a  | 04/01/2018 | 06/01/2018 | 7     |
| b  | 01/01/2018 | 04/01/2018 | 3     |
| b  | 04/01/2018 | 06/01/2018 | 4     |
+--------------------------------------+
我们看到时间序列是由不规则的间隔定义的。我想扩展每个时间序列,这样序列中每天都有一行

像这样

+--------------------------------------+
| ID | start      | end        | value |
+--------------------------------------+
| a  | 01/01/2018 | 02/01/2018 | 5     |
| a  | 02/01/2018 | 03/01/2018 | 5     |
| a  | 03/01/2018 | 04/01/2018 | 6     |
| a  | 04/01/2018 | 05/01/2018 | 7     |
| a  | 05/01/2018 | 06/01/2018 | 7     |
| b  | 01/01/2018 | 02/01/2018 | 3     |
| b  | 02/01/2018 | 03/01/2018 | 3     |
| b  | 03/01/2018 | 04/01/2018 | 3     |
| b  | 04/01/2018 | 05/01/2018 | 4     |
| b  | 05/01/2018 | 06/01/2018 | 4     |
+--------------------------------------+
在SQL中是否可以从前一个表中获取后一个表,如果可以,请为我指出正确的方向

注意:每个时间序列是连续的,没有重叠的间隔

你可以试试这个

DECLARE @T TABLE (ID VARCHAR(2),  start DATE, [end] DATE, value INT )
INSERT INTO @T VALUES
( 'a', '01/01/2018', '01/03/2018', 5 ),
( 'a', '01/03/2018', '01/04/2018', 6 ),
( 'a', '01/04/2018', '01/06/2018', 7 ),
( 'b', '01/01/2018', '01/04/2018', 3 ),
( 'b', '01/04/2018', '01/06/2018', 4 )


;WITH CTE AS (
    SELECT * FROM @T 
    UNION ALL
    SELECT T.ID, DATEADD(DAY,1, CTE.start) Start, T.[end], T.value 
    FROM @T T 
        INNER JOIN CTE ON T.ID = CTE.ID AND T.value = CTE.value 
            AND DATEADD(DAY,1, CTE.start)  < T.[end]
)
SELECT ID , start, DATEADD(DAY,1, start) [end], value FROM CTE
ORDER BY ID, start

这种方法将原始表与0中的整数表联接,只选择那些小于日期差的整数。选定的每一行都提供扩展日期范围的一条记录。我假设原始数据中的日期间隔不超过9999天,但如果是这样,您可以通过添加一行来扩展整数表


编辑:我应该承认@slartidan在这个答案中生成整数列表的优雅方式

交叉应用通常是一个更快的选择。我假设你可以假设一个范围内的月数是有限的,并且你的输入日期总是在一个月的第一天

with mnths as (
    select *
    from (values (0), (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), (11)) as t(offset)
)
select *
from data
    cross apply (
        select dateadd(month, offset, start_dt) as expanded_start_dt
        from mnths
        where dateadd(month, offset, start_dt) < end_dt
    ) as m

我不明白。到目前为止,你尝试了什么?我不知道如何在没有某种循环和某种临时表的情况下填充它。你需要在查询语句中完成,或者它可以是一个过程/函数?你想创建数据来填补空白,对吗?哦,我找到了一种使用行数和DATEDIFF的方法。我在这里做实验,我会很快发布答案。谢谢你的时间。这在概念上/语法上对我来说似乎是最好的解决方案,但是它对于我的需要来说太慢了。输入表可以有O1e5行。谢谢你的评论。你是对的,对于你的问题,递归cte方法比静态数字乘法器表工作得慢。我使用这种方法,因为它足够快,可以满足我的需要。感谢您的时间。虽然有限间隔长度的假设是可以的,但从月初开始的范围不是。谢谢你的时间。很容易调整。这里最大的区别是使用交叉应用。
SELECT  T.ID, 
        DATEADD(D, V.N, T.Start) [start], 
        DATEADD(D, V.N+1, T.Start) [end], 
        T.Value
    FROM YourTable T
    JOIN (
                SELECT ones.n + 10*tens.n + 100*hundreds.n + 1000*thousands.n N
                    FROM (VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) ones(n),
                         (VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) tens(n),
                         (VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) hundreds(n),
                         (VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) thousands(n)

        ) V
    ON V.N < DATEDIFF(D, T.Start, T.[End])
with mnths as (
    select *
    from (values (0), (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), (11)) as t(offset)
)
select *
from data
    cross apply (
        select dateadd(month, offset, start_dt) as expanded_start_dt
        from mnths
        where dateadd(month, offset, start_dt) < end_dt
    ) as m