计算连续行 - SQL Server 2008
Counting consecutive rows - SQL Server 2008
我需要根据其他列中的值计算连续的行数。
关于 SQL 我完全是个新手 - 所以如果有什么不清楚的地方请问。
我有 SQL Server 2008,所以 LEAD()
和 LAG()
没有发挥作用,与 OVER() 相同,window 大小基于分区。
示例数据集:
SLOT Blocked
-------------------------------
2015-02-09 07:00:00.000 0
2015-02-09 07:15:00.000 0
2015-02-09 07:30:00.000 0
2015-02-09 07:45:00.000 1
2015-02-09 08:00:00.000 1
2015-02-09 08:15:00.000 1
2015-02-09 08:30:00.000 0
2015-02-09 08:45:00.000 0
2015-02-09 09:00:00.000 0
2015-02-09 09:15:00.000 0
2015-02-09 09:30:00.000 1
2015-02-09 09:45:00.000 1
2015-02-09 10:00:00.000 1
2015-02-09 10:15:00.000 1
2015-02-09 10:30:00.000 0
2015-02-09 10:45:00.000 0
2015-02-09 11:00:00.000 0
2015-02-09 11:15:00.000 0
2015-02-09 11:30:00.000 0
2015-02-09 11:45:00.000 0
2015-02-09 12:00:00.000 0
数据按SLOT
排序。我想计算分区 where Blocked = 0
.
上的行数
我想得到的结果集:
SLOT Blocked RowNum
-------------------------------------------
2015-02-09 07:00:00.000 0 1
2015-02-09 07:15:00.000 0 2
2015-02-09 07:30:00.000 0 3
2015-02-09 07:45:00.000 1 0
2015-02-09 08:00:00.000 1 0
2015-02-09 08:15:00.000 1 0
2015-02-09 08:30:00.000 0 1
2015-02-09 08:45:00.000 0 2
2015-02-09 09:00:00.000 0 3
2015-02-09 09:15:00.000 0 4
2015-02-09 09:30:00.000 1 0
2015-02-09 09:45:00.000 1 0
2015-02-09 10:00:00.000 1 0
2015-02-09 10:15:00.000 1 0
2015-02-09 10:30:00.000 0 1
2015-02-09 10:45:00.000 0 2
2015-02-09 11:00:00.000 0 3
2015-02-09 11:15:00.000 0 4
2015-02-09 11:30:00.000 0 5
2015-02-09 11:45:00.000 0 6
2015-02-09 12:00:00.000 0 7
提前致谢!
对于SQL Server 2008你可以这样解决
SELECT Slot
,Blocked
,CASE WHEN Blocked = 0
THEN ROW_NUMBER() OVER
(PARTITION BY rt.RunningTotal ORDER BY Slot)
ELSE 0 END RowNum
FROM Table1 t
CROSS APPLY (SELECT ISNULL(SUM(Blocked), 0) RunningTotal
FROM Table1
WHERE Slot < t.Slot
) rt
ORDER BY Slot
(将表 1 替换为您的 table 姓名)
SQL Fiddle: http://sqlfiddle.com/#!3/659a0/28
由于您使用的是sql server 2008,所以需要使用row_number() over。
计算有点复杂,但是这个脚本可以从 sql server 2005 运行。
;WITH CTE AS
(
SELECT SLOT, row_number() over (order by SLOT)-
row_number() over (partition by blocked order by SLOT) x, blocked
FROM
-- replace these lines with your real table
--start test tabel
(values
(cast( '2015-02-09 07:00:00.000' as datetime), 0)
,('2015-02-09 07:15:00.000', 0),('2015-02-09 07:30:00.000', 0)
,('2015-02-09 07:45:00.000', 1),('2015-02-09 08:00:00.000', 1)
,('2015-02-09 08:15:00.000', 1),('2015-02-09 08:30:00.000', 0)
,('2015-02-09 08:45:00.000', 0),('2015-02-09 09:00:00.000', 0)
,('2015-02-09 09:15:00.000', 0),('2015-02-09 09:30:00.000', 1)
,('2015-02-09 09:45:00.000', 1),('2015-02-09 10:00:00.000', 1)
,('2015-02-09 10:15:00.000', 1),('2015-02-09 10:30:00.000', 0)
,('2015-02-09 10:45:00.000', 0),('2015-02-09 11:00:00.000', 0)
,('2015-02-09 11:15:00.000', 0),('2015-02-09 11:30:00.000', 0)
,('2015-02-09 11:45:00.000', 0),('2015-02-09 12:00:00.000', 0)) x(SLOT,Blocked )
-- end test tabel
)
SELECT
SLOT,
BLOCKED,
CASE WHEN blocked = 0
THEN
row_number() over (partition by x, blocked order by slot)
ELSE 0 end ROWNUMBER
FROM cte
ORDER BY slot
有趣的问题..!!
我能够使用以下代码实现此目的:
CREATE TABLE #TestTable(SLOT DATETIME,BLOCKED INT);
INSERT #TestTable(SLOT,BLOCKED)
VALUES
('2015-02-09 07:00:00.000' ,0),
('2015-02-09 07:15:00.000' ,0),
('2015-02-09 07:30:00.000' ,0),
('2015-02-09 07:45:00.000' ,1),
('2015-02-09 08:00:00.000' ,1),
('2015-02-09 08:15:00.000' ,1),
('2015-02-09 08:30:00.000' ,0),
('2015-02-09 08:45:00.000' ,0),
('2015-02-09 09:00:00.000' ,0),
('2015-02-09 09:15:00.000' ,0),
('2015-02-09 09:30:00.000' ,1),
('2015-02-09 09:45:00.000' ,1),
('2015-02-09 10:00:00.000' ,1),
('2015-02-09 10:15:00.000' ,1),
('2015-02-09 10:30:00.000' ,0),
('2015-02-09 10:45:00.000' ,0),
('2015-02-09 11:00:00.000' ,0),
('2015-02-09 11:15:00.000' ,0),
('2015-02-09 11:30:00.000' ,0),
('2015-02-09 11:45:00.000' ,0),
('2015-02-09 12:00:00.000' ,0)
SELECT *
FROM #TestTable
ORDER BY SLOT
;WITH TestTableVw AS
(SELECT SLOT,BLOCKED,ROW_NUMBER() OVER(ORDER BY SLOT) RNum
FROM #TestTable
)
SELECT T.SLOT,T.BLOCKED,CASE WHEN T.BLOCKED=0 THEN V1.RNum-ISNULL((SELECT MAX(V2.RNum) FROM TestTableVw V2 WHERE V2.RNum<V1.RNum AND V2.BLOCKED=1),0) ELSE 0 END
FROM #TestTable T
JOIN TestTableVw V1 ON T.SLOT=V1.SLOT
DROP TABLE #TestTable;
我希望这会有所帮助..!!
谢谢,
Swapnil
我需要根据其他列中的值计算连续的行数。
关于 SQL 我完全是个新手 - 所以如果有什么不清楚的地方请问。
我有 SQL Server 2008,所以 LEAD()
和 LAG()
没有发挥作用,与 OVER() 相同,window 大小基于分区。
示例数据集:
SLOT Blocked
-------------------------------
2015-02-09 07:00:00.000 0
2015-02-09 07:15:00.000 0
2015-02-09 07:30:00.000 0
2015-02-09 07:45:00.000 1
2015-02-09 08:00:00.000 1
2015-02-09 08:15:00.000 1
2015-02-09 08:30:00.000 0
2015-02-09 08:45:00.000 0
2015-02-09 09:00:00.000 0
2015-02-09 09:15:00.000 0
2015-02-09 09:30:00.000 1
2015-02-09 09:45:00.000 1
2015-02-09 10:00:00.000 1
2015-02-09 10:15:00.000 1
2015-02-09 10:30:00.000 0
2015-02-09 10:45:00.000 0
2015-02-09 11:00:00.000 0
2015-02-09 11:15:00.000 0
2015-02-09 11:30:00.000 0
2015-02-09 11:45:00.000 0
2015-02-09 12:00:00.000 0
数据按SLOT
排序。我想计算分区 where Blocked = 0
.
我想得到的结果集:
SLOT Blocked RowNum
-------------------------------------------
2015-02-09 07:00:00.000 0 1
2015-02-09 07:15:00.000 0 2
2015-02-09 07:30:00.000 0 3
2015-02-09 07:45:00.000 1 0
2015-02-09 08:00:00.000 1 0
2015-02-09 08:15:00.000 1 0
2015-02-09 08:30:00.000 0 1
2015-02-09 08:45:00.000 0 2
2015-02-09 09:00:00.000 0 3
2015-02-09 09:15:00.000 0 4
2015-02-09 09:30:00.000 1 0
2015-02-09 09:45:00.000 1 0
2015-02-09 10:00:00.000 1 0
2015-02-09 10:15:00.000 1 0
2015-02-09 10:30:00.000 0 1
2015-02-09 10:45:00.000 0 2
2015-02-09 11:00:00.000 0 3
2015-02-09 11:15:00.000 0 4
2015-02-09 11:30:00.000 0 5
2015-02-09 11:45:00.000 0 6
2015-02-09 12:00:00.000 0 7
提前致谢!
对于SQL Server 2008你可以这样解决
SELECT Slot
,Blocked
,CASE WHEN Blocked = 0
THEN ROW_NUMBER() OVER
(PARTITION BY rt.RunningTotal ORDER BY Slot)
ELSE 0 END RowNum
FROM Table1 t
CROSS APPLY (SELECT ISNULL(SUM(Blocked), 0) RunningTotal
FROM Table1
WHERE Slot < t.Slot
) rt
ORDER BY Slot
(将表 1 替换为您的 table 姓名)
SQL Fiddle: http://sqlfiddle.com/#!3/659a0/28
由于您使用的是sql server 2008,所以需要使用row_number() over。 计算有点复杂,但是这个脚本可以从 sql server 2005 运行。
;WITH CTE AS
(
SELECT SLOT, row_number() over (order by SLOT)-
row_number() over (partition by blocked order by SLOT) x, blocked
FROM
-- replace these lines with your real table
--start test tabel
(values
(cast( '2015-02-09 07:00:00.000' as datetime), 0)
,('2015-02-09 07:15:00.000', 0),('2015-02-09 07:30:00.000', 0)
,('2015-02-09 07:45:00.000', 1),('2015-02-09 08:00:00.000', 1)
,('2015-02-09 08:15:00.000', 1),('2015-02-09 08:30:00.000', 0)
,('2015-02-09 08:45:00.000', 0),('2015-02-09 09:00:00.000', 0)
,('2015-02-09 09:15:00.000', 0),('2015-02-09 09:30:00.000', 1)
,('2015-02-09 09:45:00.000', 1),('2015-02-09 10:00:00.000', 1)
,('2015-02-09 10:15:00.000', 1),('2015-02-09 10:30:00.000', 0)
,('2015-02-09 10:45:00.000', 0),('2015-02-09 11:00:00.000', 0)
,('2015-02-09 11:15:00.000', 0),('2015-02-09 11:30:00.000', 0)
,('2015-02-09 11:45:00.000', 0),('2015-02-09 12:00:00.000', 0)) x(SLOT,Blocked )
-- end test tabel
)
SELECT
SLOT,
BLOCKED,
CASE WHEN blocked = 0
THEN
row_number() over (partition by x, blocked order by slot)
ELSE 0 end ROWNUMBER
FROM cte
ORDER BY slot
有趣的问题..!!
我能够使用以下代码实现此目的:
CREATE TABLE #TestTable(SLOT DATETIME,BLOCKED INT);
INSERT #TestTable(SLOT,BLOCKED)
VALUES
('2015-02-09 07:00:00.000' ,0),
('2015-02-09 07:15:00.000' ,0),
('2015-02-09 07:30:00.000' ,0),
('2015-02-09 07:45:00.000' ,1),
('2015-02-09 08:00:00.000' ,1),
('2015-02-09 08:15:00.000' ,1),
('2015-02-09 08:30:00.000' ,0),
('2015-02-09 08:45:00.000' ,0),
('2015-02-09 09:00:00.000' ,0),
('2015-02-09 09:15:00.000' ,0),
('2015-02-09 09:30:00.000' ,1),
('2015-02-09 09:45:00.000' ,1),
('2015-02-09 10:00:00.000' ,1),
('2015-02-09 10:15:00.000' ,1),
('2015-02-09 10:30:00.000' ,0),
('2015-02-09 10:45:00.000' ,0),
('2015-02-09 11:00:00.000' ,0),
('2015-02-09 11:15:00.000' ,0),
('2015-02-09 11:30:00.000' ,0),
('2015-02-09 11:45:00.000' ,0),
('2015-02-09 12:00:00.000' ,0)
SELECT *
FROM #TestTable
ORDER BY SLOT
;WITH TestTableVw AS
(SELECT SLOT,BLOCKED,ROW_NUMBER() OVER(ORDER BY SLOT) RNum
FROM #TestTable
)
SELECT T.SLOT,T.BLOCKED,CASE WHEN T.BLOCKED=0 THEN V1.RNum-ISNULL((SELECT MAX(V2.RNum) FROM TestTableVw V2 WHERE V2.RNum<V1.RNum AND V2.BLOCKED=1),0) ELSE 0 END
FROM #TestTable T
JOIN TestTableVw V1 ON T.SLOT=V1.SLOT
DROP TABLE #TestTable;
我希望这会有所帮助..!!
谢谢,
Swapnil