Гибкое рабочее окно для подсчета записей в пределах временного диапазона - PullRequest
1 голос
/ 17 апреля 2019

У меня есть несколько устройств в полевых условиях, отправляющих данные по 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 (первый столбец) createt на сервере, а last last (второй столбец) - это временная метка от устройства, очевидно, чтозадержка процесса отправки.

Для каждого датчика от моего устройства я получаю отдельную запись, поэтому мне просто нужно подсчитать строки, чтобы получить представление о том, сколько точек данных было сохранено на устройстве в определенном диапазоне.времени (это зависит от поведения устройства).

Теперь мне нравится группировать по меткам времени, чтобы оценить для каждой из этих меток времени, сколько наборов данных уже создано, но не достигло сервераso тарифы.

Итак, для каждой временной отметки я хотел бы знать количество строк в наборе данных, которые имеютвременная метка в будущем, но последняя изменилась в прошлом.

Поскольку мой набор данных очень большой, я бы хотел избежать выборки.

И да, это не должен быть анализ во времениМне просто нужно, чтобы понять поведение устройства и настроить некоторые параметры.

Я уже пробовал это:

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

Ответы [ 2 ]

0 голосов
/ 07 июня 2019

Это должно перевести в подзапрос, что-то вроде этого:

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 может помочь, но нужно знать больше о ваших данных, распределении и объемах.

0 голосов
/ 18 апреля 2019

В качестве возможного ответа на мой собственный вопрос я хотел бы показать опцию fetch-Option, которая работает и производит вывод, который я ищу. Но так как мне нужно работать в Azure Datewarehouse, выборка невозможна собственным способом. Поскольку я интегрировал свою таблицу в качестве внешнего ресурса на классическом SQL-сервере в Azure и использовал выборку таким образом, ей потребовалось 9 минут для строк по 80 КБ и 391 разная отметка времени в этих строках. Так что это просто не хороший вариант.

Но, рабочее решение выглядит так (я сосредоточил внимание на одномодовом диапазоне только один идентификатор, чтобы уменьшить объем данных.)

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]; 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...