Sql-获取特定条件下百万+行的时间范围
Sql-Get time ranges from million+ rows for particular condition
我正在使用 SQL Server 2012,我有一个 table 大约有 35 列和 10+ 百万行。
我需要从任何特定列的值匹配的数据中找到时间范围
例如。
样本数据如下
Datetime col1 col2 col3
2018-05-31 0:00 1 2 1
2018-05-31 13:00 2 2 2
2018-05-31 14:30 3 2 1
2018-05-31 15:00 4 3 1
2018-05-31 16:00 4 5 1
2018-05-31 17:00 3 2 2
2018-05-31 17:30 3 2 4
2018-05-31 18:00 2 2 4
2018-05-31 20:00 1 2 6
2018-05-31 21:00 2 2 3
2018-05-31 21:10 2 2 1
2018-05-31 22:00 1 6 3
2018-05-31 22:00 4 5 1
2018-05-31 23:59 4 7 2
从col2值=<2的数据中找到时间范围,因此我的预期结果集如下
Start Time End time Time Diff
2018-05-31 0:00 2018-05-31 14:30 14:30:00
2018-05-31 17:00 2018-05-31 21:10 4:10:00
我可以用下面的逻辑实现同样的效果,但是速度非常慢
我得到所有行然后
按date_Time排序
扫描行获取值完全匹配的第一行,并将该时间戳记录为开始时间。
扫描更多行,直到我得到条件被打破的行,并将该时间戳记录为结束时间。
但是因为我必须玩大号。 Of rows, overall this will make my operation slow, any inputs or pseudo code to improve same.
我们可以在这里使用稍微修改的行号差异方法。第一个标记为 cte1
的 CTE 的目的是添加一个计算列来标记我们想要的岛屿,col2
值 <= 2,为 1,其他所有为 0。然后,我们可以计算两个行号的差异,并聚合所有岛屿以找到开始和结束时间,以及这些时间之间的差异。
WITH cte1 AS (
SELECT *,
CASE WHEN col2 <= 2 THEN 1 ELSE 0 END AS class
FROM yourTable
),
cte2 AS (
SELECT *,
ROW_NUMBER() OVER (ORDER BY Datetime) -
ROW_NUMBER() OVER (PARTITION BY class ORDER BY Datetime) rn
FROM cte1
)
SELECT
MIN(Datetime) AS [Start Time],
MAX(Datetime) AS [End Time],
CONVERT(TIME, MAX(Datetime) - MIN(Datetime)) AS [Time Diff]
FROM cte2
WHERE class = 1
GROUP BY rn
ORDER BY MIN(Datetime);
我正在使用 SQL Server 2012,我有一个 table 大约有 35 列和 10+ 百万行。 我需要从任何特定列的值匹配的数据中找到时间范围 例如。 样本数据如下
Datetime col1 col2 col3
2018-05-31 0:00 1 2 1
2018-05-31 13:00 2 2 2
2018-05-31 14:30 3 2 1
2018-05-31 15:00 4 3 1
2018-05-31 16:00 4 5 1
2018-05-31 17:00 3 2 2
2018-05-31 17:30 3 2 4
2018-05-31 18:00 2 2 4
2018-05-31 20:00 1 2 6
2018-05-31 21:00 2 2 3
2018-05-31 21:10 2 2 1
2018-05-31 22:00 1 6 3
2018-05-31 22:00 4 5 1
2018-05-31 23:59 4 7 2
从col2值=<2的数据中找到时间范围,因此我的预期结果集如下
Start Time End time Time Diff
2018-05-31 0:00 2018-05-31 14:30 14:30:00
2018-05-31 17:00 2018-05-31 21:10 4:10:00
我可以用下面的逻辑实现同样的效果,但是速度非常慢 我得到所有行然后
按date_Time排序
扫描行获取值完全匹配的第一行,并将该时间戳记录为开始时间。
扫描更多行,直到我得到条件被打破的行,并将该时间戳记录为结束时间。
但是因为我必须玩大号。 Of rows, overall this will make my operation slow, any inputs or pseudo code to improve same.
我们可以在这里使用稍微修改的行号差异方法。第一个标记为 cte1
的 CTE 的目的是添加一个计算列来标记我们想要的岛屿,col2
值 <= 2,为 1,其他所有为 0。然后,我们可以计算两个行号的差异,并聚合所有岛屿以找到开始和结束时间,以及这些时间之间的差异。
WITH cte1 AS (
SELECT *,
CASE WHEN col2 <= 2 THEN 1 ELSE 0 END AS class
FROM yourTable
),
cte2 AS (
SELECT *,
ROW_NUMBER() OVER (ORDER BY Datetime) -
ROW_NUMBER() OVER (PARTITION BY class ORDER BY Datetime) rn
FROM cte1
)
SELECT
MIN(Datetime) AS [Start Time],
MAX(Datetime) AS [End Time],
CONVERT(TIME, MAX(Datetime) - MIN(Datetime)) AS [Time Diff]
FROM cte2
WHERE class = 1
GROUP BY rn
ORDER BY MIN(Datetime);