SQL Server:间隙/孤岛、日期时间、连续块365天块

SQL Server:间隙/孤岛、日期时间、连续块365天块,sql,sql-server,gaps-and-islands,Sql,Sql Server,Gaps And Islands,我有一张这样的桌子:- tblMeterReadings id仪表周期\开始周期\结束金额 1 2014-01-01 00:00 2014-01-01 00:29:59 100.3 212014-01-01 00:30 2014-01-01 00:59:59 50.5 31 2014-01-01 01:00 2014-01-01 01:29:59 70.7 412014-01-01 01:30 2014-01-01 01:59:59 900.1 512014-01-0102:002014-01-

我有一张这样的桌子:-

tblMeterReadings

id仪表周期\开始周期\结束金额
1 2014-01-01 00:00 2014-01-01 00:29:59 100.3
212014-01-01 00:30 2014-01-01 00:59:59 50.5
31 2014-01-01 01:00 2014-01-01 01:29:59 70.7
412014-01-01 01:30 2014-01-01 01:59:59 900.1
512014-01-0102:002014-01-0102:29:59400.0
612014-01-01 02:30 2014-01-01 02:59:59 200.3
7.1 2014-01-01 03:00 2014-01-01 03:29:59 100.8
812014-01-0103:302014-01-0103:59:59140.3

这是一个从“2014-01-01 00:00”到“2014-01-01 3:59:59”的小“连续块”

在实数表中,存在长度为年的“连续块”

我需要找到最近连续365个完整日的时段开始和时段结束(按米列归档)

当我说完成天数时我指的是条目范围从
00:00到23:59的一天。
当我说“连续”时,我的意思是说一定不会有天不见了

我想选择构成此连续完整天数块的所有行

我还需要一个输出,如:

区块\u开始区块\u结束区块的总金额\u
2013-02-26 00:00 2014-02-26 23:59:59 1034234.5

这是我无法理解的,所以如果有人能解决。。。我会留下深刻印象的

您可以尝试以下方法:

Select MIN(period_start) as "block start"
     , MAX(period_end) as "block end"
     , SUM(amount) as "total amount"
FROM YourTable
GROUP BY    datepart(year, period_start)
        ,   datepart(month, period_start)
        ,   datepart(day, period_start)
        ,   datepart(year, period_end)
        ,   datepart(month, period_end)
        ,   datepart(day, period_end)
Having      datepart(year, period_start) = datepart(year, period_end)
        AND datepart(month, period_start) = datepart(month, period_end)
        AND datepart(day, period_start) = datepart(day, period_end)
        AND datepart(hour,  MIN(period_start)) = 0 
        AND datepart(minute,MIN(period_start)) = 0
        AND datepart(hour,  MAX(period_end)) = 23
        AND datepart(minute,MIN(period_end)) = 59

因为您的粒度是1秒,所以您需要以1秒的间隔将时段扩展到开始和结束之间的所有日期/时间。要做到这一点,您需要交叉连接数字表(数字表是通过对任意系统视图中的对象ID进行排序而动态生成的,我将其限制为TOP 86400,因为这是一天中的秒数,并且您已经声明您的时间段不会超过一天):


尝试搜索
伊兹克-本-甘缺口岛
该时段是如何开始的?这总是半小时从整小时开始吗?如果没有,它能在一天开始,在另一天结束吗?完整的一天-记录一天中每30分钟一次?@JakubKania间隙可能不是半小时,但始终在00:00到23:59:59之间,不会跨越到另一天。@rudym组成完整一天的部分可能不是30分钟,为免生疑问,它可以是从00:00开始读到23:59:59,或者三读一读一读从00:00:00到01:19:59,然后再读一读从01:20:00到3:44:59,最后一读从3:45:00到23:59:59。我认为这并不能解决问题。。。它比那更复杂。看起来它能完成任务。。。非常感谢。86400的意义是什么?你能添加一些评论来帮助我理解发生了什么吗?还有。。。如果你在设计这个,你会做时间跨度为00:00:00->00:30:00,00:30:00到01:00:00,或者,我是怎么做的?86400只是一天中的秒数,这是如果你的周期跨度不超过一天所需的最大数。是的,我建议结束日期时间不包括期间,因此
00:00:00->00:30:00,00:30:00->01:00:00
。对于这个特定的查询,它没有多大区别,但对于其他查询,它可能会有很大区别。这篇文章几乎涵盖了我的推理:谢谢。我将更改跨度,以反映您的评论。如果我这样做,您会更改您的查询,还是我应该这样做?
WITH Numbers AS
(   SELECT  TOP (86400) 
            Number = ROW_NUMBER() OVER(ORDER BY a.object_id) - 1
    FROM    sys.all_objects a
            CROSS JOIN sys.all_objects b
    ORDER BY a.object_id
)
SELECT  r.ID, r.meter, dt.[DateTime]
FROM    tblMeterReadings r
        CROSS JOIN Numbers n
        OUTER APPLY 
        (   SELECT [DateTime] = DATEADD(SECOND, n.Number, r.period_start)
        ) dt
WHERE   dt.[DateTime] <= r.Period_End;
WITH Numbers AS
(   SELECT  TOP (86400) 
            Number = ROW_NUMBER() OVER(ORDER BY a.object_id) - 1
    FROM    sys.all_objects a
            CROSS JOIN sys.all_objects b
    ORDER BY a.object_id
), Grouped AS
(   SELECT  r.meter, 
            Amount = CASE WHEN Number = 1 THEN r.Amount ELSE 0 END,
            dt.[DateTime],
            GroupingSet = DATEADD(SECOND, 
                                    -DENSE_RANK() OVER(PARTITION BY r.Meter 
                                                        ORDER BY dt.[DateTime]), 
                                    dt.[DateTime])
    FROM    tblMeterReadings r
            CROSS JOIN Numbers n
            OUTER APPLY 
            (   SELECT [DateTime] = DATEADD(SECOND, n.Number, r.period_start)
            ) dt
    WHERE   dt.[DateTime] <= r.Period_End
)
SELECT  meter, 
        PeriodStart = MIN([DateTime]), 
        PeriodEnd = MAX([DateTime]), 
        Amount = SUM(Amount)
FROM    Grouped
GROUP BY meter, GroupingSet
HAVING DATEADD(YEAR, 1, MIN([DateTime])) < MAX([DateTime]);
meter | PeriodStart         | PeriodEnd           | Amount
------+---------------------+---------------------+----------
1     | 2014-01-01 00:00:00 | 2014-01-01 03:59:59 |  1963