sql - 灵活的运行窗口,可对时间范围内的条目进行计数

标签 sql azure join time-series sql-data-warehouse

我在现场有一些设备,通过 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');

由于时间戳(第一列)的值是在服务器上创建的,而上次更改(第二列)是来自设备的时间戳,因此明显的区别是发送过程的延迟。

从我设备的每个传感器中,我都会得到一个单独的条目,因此我只需要计算行数即可了解在特定时间范围内设备上存储了多少数据点(这会有所不同,具体取决于设备)。

现在我喜欢按时间戳分组来评估每个时间戳,已经创建了多少数据集,但尚未到达服务器。

因此,对于每个时间戳,我想知道数据集中的行数,这些行的时间戳是 future 的,但最后更改的时间是过去的。

由于我的数据集非常大,我想避免任何抓取。

是的,这不应该是实时分析,我只需要它来了解设备的行为并调整一些参数。

我已经尝试过这个:

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 和子查询不会有帮助,因为我需要一步完成过滤和计数。据我了解,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 上工作,因此无法以 native 方式获取。当我将表作为外部资源集成到 Azure 上的经典 SQL-Server 上并使用这种方式获取时,80k 行和这些行中的 391 个不同时间戳需要 9 分钟。所以这不是一个好的选择。

但是,可行的解决方案看起来像(我专注于一天范围一个 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]; 

关于sql - 灵活的运行窗口,可对时间范围内的条目进行计数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55732180/

相关文章:

sql - 是否可以动态提供 sp_ExecuteSql 参数名称?

c# - New-AzurePIMRequest 作为 .net 函数?

json - Azure 逻辑应用对 SQL 行的 HTTP 响应正文

mysql - 在已连接的表上连接表

c# - LINQ 中多个左连接的正确语法?

php - 当只有第一个表中的键可用时,sql 获取第二个表中的所有条目

mysql - 根据用户id统计出现次数

sql - 返回 UPDATE 结果的存储过程

azure - ARM 模板子数组

sql - 加入问题