2017-03-27 56 views
2

需要創建一個查詢,該查詢會獲取位設置爲ON/OFF的時間摘要。TSQL - 帶條件的時間總和列

例子:

╔═══════════════════════════╗ 
║   TABLE   ║ 
╠════╦════════╦═════╦═══════╣ 
║ ID ║ TIME ║ BIT ║ VALUE ║ 
╠════╬════════╬═════╬═══════╣ 
║ 1 ║ 13:40 ║ 1 ║ 5 ║ 
║ 2 ║ 13:45 ║ 1 ║ 3 ║ 
║ 3 ║ 13:50 ║ 1 ║ 1 ║ 
║ 4 ║ 13:55 ║ 0 ║ 2 ║ 
║ 5 ║ 14:00 ║ 0 ║ 7 ║ 
║ 6 ║ 14:05 ║ 1 ║ 3 ║ 
║ 7 ║ 14:10 ║ 1 ║ 4 ║ 
║ 8 ║ 14:15 ║ 0 ║ 2 ║ 
║ 9 ║ 14:20 ║ 1 ║ 2 ║ 
╚════╩════════╩═════╩═══════╝ 

我想有TIME(和VALUE - 簡單的一個)總總結時BITSET ON

13:40 - 13:50 = 10 mins 
14:05 - 14:10 = 5 mins 
14:20   = no end time, 0 mins 
----------------------------------------- 
       15 mins 

有沒有發現:

我想,這可能是作爲遞歸函數完成(傳遞最後處理的日期時間),它將通過處理的最後日期,並且計算自BITON以來的日期時間。

SQL查詢求和值(容易的):

SELECT SUM(Value) 
FROM Table 
WHERE Bit = 1 

我應該如何獲得分鐘(時間)的總價值,在此期間是BIT設置ON


編輯:查詢,可用於測試:

DECLARE @Table TABLE(
    ID INT Identity(1,1) PRIMARY KEY, 
    [TIME] DATETIME NOT NULL, 
    [BIT] BIT NOT NULL, 
    [VALUE] INT NOT NULL 
); 
INSERT INTO @Table([TIME],[BIT],[VALUE]) VALUES('13:40',1,5); 
INSERT INTO @Table([TIME],[BIT],[VALUE]) VALUES('13:45',1,3); 
INSERT INTO @Table([TIME],[BIT],[VALUE]) VALUES('13:50',1,1); 
INSERT INTO @Table([TIME],[BIT],[VALUE]) VALUES('13:55',0,2); 
INSERT INTO @Table([TIME],[BIT],[VALUE]) VALUES('14:00',0,7); 
INSERT INTO @Table([TIME],[BIT],[VALUE]) VALUES('14:05',1,3); 
INSERT INTO @Table([TIME],[BIT],[VALUE]) VALUES('14:10',1,4); 
INSERT INTO @Table([TIME],[BIT],[VALUE]) VALUES('14:15',0,2); 
INSERT INTO @Table([TIME],[BIT],[VALUE]) VALUES('14:20',1,2); 
SELECT * FROM @Table; 

回答

2

使用LEAD函數獲取下一行的時間並計算時間間隔。然後只是組結果由[位]

WITH t AS(
SELECT 
    [time], 
    DATEDIFF(minute, [time], LEAD([time], 1, null) OVER (ORDER BY [time])) AS interval, 
    [bit], 
    [value] 
FROM table1) 
SELECT [bit], CAST(DATEADD(MINUTE, SUM(interval), '00:00') AS TIME), SUM([value]) FROM t 
GROUP BY [bit] 
+0

這真的很容易閱讀,也很容易理解。感謝你的回答! – Tatranskymedved

+0

更新:使用OVER(ORDER BY [時間])而不是(BY [id])。因爲ID不一定是連續的。它可能是guid或自然的關鍵 – usart

2

你有兩個問題:總結的時間,並確定相鄰值。你可以用行號的方法處理第二個。您可以通過轉換爲分鐘處理前:

select bit, min(time), max(time), 
     sum(datediff(minute, 0, time)) as minutes, 
     sum(value) 
from (select t.*, 
      row_number() over (order by id) as seqnum, 
      row_number() over (partition by bit order by id) as seqnum_b 
     from t 
    ) t 
group by (seqnum - seqnum_b), bit; 
+0

感謝您的回答!然而,當距離(Seqnum - seqnum_b)對於更多情況相同時,我發現有一個問題,對於聚合函數,您會得到錯誤的結果 - 'MIN'首先發生,'MAX'將最後一次發生。 – Tatranskymedved

+0

@Transranskymedved。 。 。你試過這個嗎?這可以找到相鄰的行。也許你在'group by'中省略了'bit'。 –

+0

TBH還沒有嘗試過,但我現在已經測試過了。這是一段聰明的代碼!感謝這個想法,我永遠不會想象這可以通過這種方式完成。無論如何,這不是對主題的完整回答,它只涉及其中的一部分。感謝您的時間! =) – Tatranskymedved

1

這是一個「空白和孤島」的問題,有一個非常標準的解決方案。我想出了這個,這與Gordon的幾乎相同,但是有一個額外的步驟來計算間隔。這是我發佈基本上是重複答案的唯一原因,我不確定在零分鐘之內取得差異實際上有效嗎?

DECLARE @table TABLE (id int, [time] TIME, [bit] BIT, value INT); 
INSERT INTO @table SELECT 1, '13:40', 1, 5; 
INSERT INTO @table SELECT 2, '13:45', 1, 3; 
INSERT INTO @table SELECT 3, '13:50', 1, 1; 
INSERT INTO @table SELECT 4, '13:55', 0, 2; 
INSERT INTO @table SELECT 5, '14:00', 0, 7; 
INSERT INTO @table SELECT 6, '14:05', 1, 3; 
INSERT INTO @table SELECT 7, '14:10', 1, 4; 
INSERT INTO @table SELECT 8, '14:15', 0, 2; 
INSERT INTO @table SELECT 9, '14:20', 1, 2; 
WITH x AS (
    SELECT *, ROW_NUMBER() OVER (PARTITION BY [bit] ORDER BY id) AS a_id, ROW_NUMBER() OVER (ORDER BY id) AS b_id FROM @table), 
y AS (
    SELECT [bit], MIN([time]) AS min_time, MAX([time]) AS max_time, SUM(value) AS value FROM x GROUP BY a_id - b_id, [bit]) 
SELECT [bit], SUM(value) AS total_value, SUM(DATEDIFF(MINUTE, min_time, max_time)) AS total_minutes FROM y GROUP BY [bit]; 

結果:

bit total_value total_minutes 
0 11   5 
1 18   15 

作爲獎金這裏是一個解決方案,既解決了實際問題,即有多少經過的時間是在那裏當該位被設置爲1:

WITH x AS (SELECT id, id - DENSE_RANK() OVER(ORDER BY id) AS grp FROM @table WHERE [bit] = 1), y AS (SELECT MIN(id) AS range_start, MAX(id) AS range_end FROM x GROUP BY grp) 
SELECT SUM(DATEDIFF(MINUTE, t1.[time], t2.[time])) AS minutes_elapsed FROM y INNER JOIN @table t1 ON t1.id = y.range_start INNER JOIN @table t2 ON t2.id = y.range_end; 
+0

更新後,我可以清楚地看到它是如何工作的,我有問題了解最初的查詢= /謝謝你的答案,這應該很好! – Tatranskymedved