我在现场有一些设备,通过GSM不时丢失连接来发送数据。由于我的磁盘空间有限,我倾向于在没有连接的时间段中丢失一些数据,因此我想评估待处理数据的数量以获得对情况的一些了解。
如果我将表从我的服务器减少到我需要的列,它看起来像这样:
Declare @table as table(
timestamp datetime,
lastchanged datetime )
INSERT INTO @table
VALUES
('2019-04-01 12:27:23', '2019-04-01 12:26:17'),
('2019-04-01 12:27:23', '2019-04-01 12:25:47'),
('2019-04-01 12:27:23', '2019-04-01 12:26:17'),
('2019-04-01 12:27:23', '2019-04-01 12:26:03'),
('2019-04-01 12:27:23', '2019-04-01 12:26:20'),
('2019-04-01 12:28:23', '2019-04-01 12:25:52'),
('2019-04-01 12:28:23', '2019-04-01 12:26:22'),
('2019-04-01 12:28:23', '2019-04-01 12:26:18'),
('2019-04-01 12:28:23', '2019-04-01 12:25:54'),
('2019-04-01 12:29:23', '2019-04-01 12:25:47'),
('2019-04-01 12:29:23', '2019-04-01 12:26:17'),
('2019-04-01 12:29:23', '2019-04-01 12:25:47'),
('2019-04-01 12:29:23', '2019-04-01 12:25:45'),
('2019-04-01 12:30:23', '2019-04-01 12:26:17'),
('2019-04-01 12:30:23', '2019-04-01 12:25:47'),
('2019-04-01 12:30:23', '2019-04-01 12:26:17'),
('2019-04-01 12:31:23', '2019-04-01 12:26:03'),
('2019-04-01 12:31:23', '2019-04-01 12:26:20'),
('2019-04-01 12:31:23', '2019-04-01 12:25:52'),
('2019-04-01 12:31:23', '2019-04-01 12:26:22'),
('2019-04-01 12:31:23', '2019-04-01 12:26:18'),
('2019-04-01 12:31:23', '2019-04-01 12:25:54'),
('2019-04-01 12:32:23', '2019-04-01 12:25:47'),
('2019-04-01 12:32:23', '2019-04-01 12:26:17'),
('2019-04-01 12:32:23', '2019-04-01 12:25:47'),
('2019-04-01 12:32:23', '2019-04-01 12:25:45');
当在服务器上创建timestamp(第一列)的值并且最后一次更改(第二列)是来自设备的时间戳时,differenc显然是发送过程的延迟。
从我的设备的每个传感器,我得到一个单独的条目,所以我只需要计算行数,以了解在特定时间范围内设备上存储了多少数据点(这取决于设备的行为) 。
现在,我喜欢按时间戳分组来评估每个时间戳,已经创建了多少数据集,但没有达到服务器这样的价格。
因此,对于每个时间戳,我想知道数据集中的行数,这些行在将来会有一个时间戳,但在过去会有一个时间戳。
由于我的数据集很大,我想避免任何提取。
是的,这不应该是及时分析,我只需要了解设备的行为并调整一些参数。
我已经尝试过了:
SELECT
A.timestamp,
COUNT(case when (A.timestamp < B.timestamp AND A.timestamp > B.lastchanged ) then 1 else null end) AS CountPending
FROM @table A, @table B
GROUP BY A.timestamp
ORDER BY A.timestamp
并且认为CTE和subquerys不会有帮助,因为我需要一步完成过滤和计数。据我所知,SQL中的经典运行窗口只需要窗口范围的固定数量的条目,但在我的数据集中,这个数字根本不是常量。
应用于上面的例子,结果是错误的:
2019-04-01 12:27:23.000 105
2019-04-01 12:28:23.000 68
2019-04-01 12:29:23.000 52
2019-04-01 12:30:23.000 30
2019-04-01 12:31:23.000 24
2019-04-01 12:32:23.000 0
作为我自己的问题的一个可能的答案,我想展示一个fetch-Option,它可以工作并产生我正在寻找的输出。但是,由于我需要在Azure Datewarehouse上工作,因此无法以本机方式进行提取。当我将我的表作为外部资源集成到Azure上的经典SQL-Server上并使用这种方式获取时,它需要9分钟才能获得80k行和391个不同时间戳。所以这不是一个好选择。
但是,一个工作解决方案看起来像(我专注于一天范围只有一个ID,以减少数据量。)
CREATE TABLE #st
(
[timestamp] DATETIME,
CountPending INT
);
DECLARE
@timestamp DATETIME,
@CountPending INT = 0,
@ID INT,
@Start DATETIME,
@Stop DATETIME;
SET @troID = 127
SET @Start = CAST('2019-04-01T00:00:00' AS DATETIME)
SET @Stop = CAST('2019-04-02T00:00:00' AS DATETIME)
DECLARE c CURSOR
LOCAL STATIC FORWARD_ONLY READ_ONLY
FOR
SELECT DISTINCT timestamp
FROM test.SensorData
WHERE @ID = @ID AND timestamp BETWEEN @Start AND @Stop;
OPEN c;
FETCH NEXT FROM c INTO @timestamp;
WHILE @@FETCH_STATUS = 0
BEGIN
SET @CountPending = (
SELECT COUNT(*)
FROM test.SensorData
WHERE troID = @troID AND
timestamp BETWEEN @Start AND @Stop AND
@timestamp < timestamp AND @timestamp > lastchanged)
INSERT #st([timestamp], CountPending)
SELECT @timestamp, @CountPending;
FETCH NEXT FROM c INTO @timestamp;
END
CLOSE c;
DEALLOCATE c;
SELECT [timestamp], CountPending
FROM #st
ORDER BY [timestamp];
这应该转换为子查询,如下所示:
SELECT a.troID, a.timestamp, MAX(x.c)
FROM test.SensorData a
CROSS APPLY
(
SELECT COUNT(*) c
FROM test.SensorData b
WHERE a.troID = b.troID
AND a.timestamp < b.timestamp
AND a.timestamp > b.lastchanged
) x
GROUP BY a.troID, a.timestamp
我猜想在troId
上散列可能会有所帮助,但需要了解更多有关您的数据,分布和数量的信息。