MSSQL - 按日期对开始/结束列之间的时间进行分组

时间:2015-03-18 15:58:53

标签: sql sql-server datetime

无法通过搜索找到任何内容(尽管这可能是我的搜索字词),如果有人询问/回答,请致歉。

我们在MSSQL 2012中维护设备停机记录,我正在尝试报告按天,设备,DTCode分组的停机时间。我正在运行的问题是日志表包含start&每个事件和事件的结束日期经常跨越开始和结束之间的多天(或有时是几周)。

示例数据:

Start           End             Equipment    DTCode
01/01/15 00:00  01/02/15 02:00  Line1        2

期望的结果:

Date          Equipment      DTCode   Downtime(minutes)
01/01/15      Line1          2        1440
01/02/15      Line1          2        120

修改

好的,现在我有一个性能不佳的优雅解决方案,因为我能想到的唯一方法是使用嵌套游标。这是一个新的小提琴,有一个更大的数据集和我想要调整/优化的功能解决方案:

http://sqlfiddle.com/#!6/b287e/1

2 个答案:

答案 0 :(得分:0)

如果您的意思是在两个"停机时间之间获得时间,您可以使用MYSQL连接获取PHP的值,并计算差异,然后删除这两行,并将其替换为新行,计算结果。

$query = "DELETE FROM TaBlEnAmEhErE WHERE DTCode=2";

答案 1 :(得分:0)

当我开始测试解决方案时,我提出了针对生产数据的性能更加可接受,所以我现在要用它来限制用户使用1年的报告数据范围。 / p>

除了日志数据之外,我创建了一个包含2010-2050日期的表格,所以我没有必要生成每次运行的日期,这就是我想出的:

--Variables for outer cursor
DECLARE @ID INT
,@StartDate DATETIME
,@EndDate DATETIME
,@LineID TINYINT
,@DTCode SMALLINT
--Table var to hold results
DECLARE @ResultTbl AS TABLE (
    [Date] DATE
    ,Line TINYINT
    ,DTCode SMALLINT
    ,MinDiff INT
)
--Declare cursor to loop through log data
DECLARE IDCur CURSOR local fast_forward FOR
SELECT ID
    ,StartTime
    ,EndTime
    ,EquipmentID
    ,dtcode
FROM DowntimeLog
OPEN IDCur
    FETCH NEXT FROM IDCur INTO @ID, @StartDate, @EndDate, @LineID, @DTCode
    WHILE @@FETCH_STATUS = 0
    BEGIN
        --Check if the entry spans multiple days
        IF DATEDIFF(DAY,@StartDate,@EndDate) > 0
        BEGIN
            --Declare cursor to loop through each date that pertains to the entry
            DECLARE @D DATE
            DECLARE applicableDates CURSOR LOCAL fast_forward FOR
            SELECT tDate
            FROM DateTbl
            WHERE tDate BETWEEN CAST(@StartDate AS DATE) AND CAST(@EndDate AS DATE)
            OPEN applicableDates
            FETCH NEXT FROM applicableDates INTO @D
            WHILE @@FETCH_STATUS = 0
            BEGIN
                --Determine if @D is the first date
                IF (SELECT CAST(@StartDate AS DATE)) = @D
                BEGIN
                    --If @D is the first date insert result row with minutes between start & 00:00 the next day
                    INSERT INTO @ResultTbl (
                            [Date]
                            ,Line
                            ,DTCode
                            ,MinDiff)
                        VALUES (
                            @D
                            ,@LineID
                            ,@DTCode
                            ,(SELECT DATEDIFF(MINUTE,@StartDate,DATEADD(DAY,1,@D))))
                END
                ELSE
                BEGIN
                    --Determine if @D is the last date
                    IF (SELECT DATEDIFF(MINUTE,@D,@EndDate)) < 1440
                    BEGIN
                        --If @D is the last date insert result row with minutes between @D 00:00 and end of downtime
                        INSERT INTO @ResultTbl (
                            [Date]
                            ,Line
                            ,DTCode
                            ,MinDiff)
                        VALUES (
                            @D
                            ,@LineID
                            ,@DTCode
                            ,(SELECT DATEDIFF(MINUTE,@D,@EndDate)))
                    END
                    ELSE
                    BEGIN
                        --If @D is not first or last date insert result row for the full day
                        INSERT INTO @ResultTbl (
                            [Date]
                            ,Line
                            ,DTCode
                            ,MinDiff)
                        VALUES (
                            @D
                            ,@LineID
                            ,@DTCode
                            ,1440)
                    END
                END
                FETCH NEXT FROM applicableDates INTO @D
            END
            CLOSE applicableDates
            DEALLOCATE applicableDates
        END
        ELSE
        BEGIN
            --Entry does not span multiple days, insert result row with diff between start & end
            INSERT INTO @ResultTbl (
                            [Date]
                            ,Line
                            ,DTCode
                            ,MinDiff)
                        VALUES (
                            CAST(@StartDate AS DATE)
                            ,@LineID
                            ,@DTCode
                            ,(SELECT DATEDIFF(MINUTE,@StartDate,@EndDate)))
        END
        FETCH NEXT FROM IDCur INTO @ID, @StartDate, @EndDate, @LineID, @DTCode
    END
CLOSE IDCur
DEALLOCATE IDCur
--Display Result
SELECT [Date]
        ,Line
        ,DTCode
        ,SUM(MinDiff) AS MinDown
FROM @ResultTbl
GROUP BY [Date],Line,DTCode