Средний расчет по шкале времени (SQL Server) - подготовка к построению графиков - PullRequest
1 голос
/ 31 декабря 2010

У меня есть следующая таблица в выпуске SQL Server Express:

Time Device Value
0:00 1      2
0:01 2      3
0:03 3      5
0:03 1      3
0:13 2      5
0:22 1      7
0:34 3      5
0:35 2      6
0:37 1      5

Таблица используется для регистрации событий различных устройств, которые сообщают свои последние значения. Я хотел бы подготовить данные таким образом, чтобы я представлял средние данные по шкале времени и в конечном итоге создавал диаграмму, используя эти данные. Я манипулировал данными этого примера в Excel следующим образом:

Time Average value
0:03 3,666666667
0:13 4,333333333
0:22 5,666666667
0:34 5,666666667
0:35 6
0:37 5,333333333

Итак, во время 0:03 мне нужно взять последние данные, которые у меня есть в таблице, и вычислить среднее значение. В этом случае это (3 + 3 + 5) / 3 = 3,67. Во время 0:13 шаги будут повторяться, и снова в 0:22, ...

Поскольку я хотел бы оставить все в таблице SQL (я бы не хотел создавать какой-либо сервис с C # или аналогичным, который бы захватывал данные и сохранял их в какой-то другой таблице)

Я бы хотел знать следующее:

  1. это правильный подход или я должен использовать какую-то другую концепцию расчета среднего значения для подготовки данных графика?
  2. если да, каков наилучший подход для его реализации? Табличное представление, функция в базе данных, хранимая процедура (которая будет вызвана из API построения диаграмм)?
  3. какие-либо предложения о том, как это реализовать?

Заранее спасибо. Mark

Обновление 1

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

Time    Device1Value    Device2Value    Device3Value
0:00    2           NULL            NULL
0:01    NULL            3           NULL
0:03    3           NULL            5
0:13    NULL            5           NULL
0:22    7           NULL            NULL
0:34    NULL            NULL            5
0:35    NULL            6           NULL
0:37    5           NULL            NULL

Запрос для этого должен быть:

SELECT Time,
(SELECT Stock FROM dbo.Event WHERE Time = S.Time AND Device = 1) AS Device1Value,
(SELECT Stock FROM dbo.Event WHERE Time = S.Time AND Device = 2) AS Device2Value,
(SELECT Stock FROM dbo.Event WHERE Time = S.Time AND Device = 3) AS Device3Value
FROM dbo.Event S GROUP BY Time

Что мне еще нужно сделать, так это написать пользовательскую функцию и вызвать ее в этом запросе, который записал бы последнее доступное значение в случае NULL, а если бы последнее доступное значение не существовало, оно оставило бы значение NULL. С помощью этой функции я получил бы следующие результаты:

Time    Device1Value    Device2Value    Device3Value
0:00    2           NULL            NULL
0:01    2           3           NULL
0:03    3           3           5
0:13    3           5           5
0:22    7           5           5
0:34    7           5           5
0:35    7           6           5
0:37    5           6           5

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

Кто-нибудь может подсказать, как создать пользовательскую функцию для замены значений NULL на последнее значение?

Обновление 2

Спасибо, Мартин. Этот запрос работал, но для прохождения 13.576 строк потребовалось почти 21 минута, что слишком много.

Последний запрос, который я использовал, был:

SELECT Time,
(SELECT TOP 1 Stock FROM dbo.Event e WHERE e.Time <= S.Time AND Device = 1 ORDER BY e.Time DESC) AS Device1Value,
(SELECT TOP 1 Stock FROM dbo.Event e WHERE e.Time <= S.Time AND Device = 2 ORDER BY e.Time DESC) AS Device2Value,
(SELECT TOP 1 Stock FROM dbo.Event e WHERE e.Time <= S.Time AND Device = 3 ORDER BY e.Time DESC) AS Device3Value
FROM dbo.Event S GROUP BY Time

но я расширил его до 10 устройств.

Я согласен, что это не лучший способ сделать это. Есть ли другой способ подготовить данные для вычисления среднего, потому что это занимает слишком много времени для обработки.

Ответы [ 2 ]

0 голосов
/ 31 декабря 2010

Таким образом, одно из возможных решений, которое я нашел, гораздо более эффективно (менее чем за секунду для 14,574 строк). У меня еще не было времени подробно рассмотреть результаты, но, с одной стороны, это выглядит многообещающе. Это код для примера 3 устройств: ВЫБЕРИТЕ Время,
SUM (CASE MAC WHEN '1' THEN Stock ELSE 0 END) Device1Value, SUM (CASE MAC WHEN '2' THEN Stock ELSE 0 END) Device1Value, SUM (CASE MAC WHEN '3' THEN Stock ELSE 0 END) Device1Value, ОТ dbo.Event GROUP BY Time ЗАКАЗАТЬ ПО ВРЕМЕНИ

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

0 голосов
/ 31 декабря 2010

Вот один из способов. Он использует подход «Quirky Update» для заполнения пробелов. Это основано на недокументированном поведении, поэтому вы можете использовать курсор для этого.

DECLARE @SourceData TABLE([Time] TIME, Device INT, value FLOAT) 

INSERT INTO @SourceData
SELECT '0:00',1,2 UNION ALL
SELECT '0:01',2,3 UNION ALL
SELECT '0:03',3,5 UNION ALL
SELECT '0:03',1,3 UNION ALL
SELECT '0:13',2,5 UNION ALL
SELECT '0:22',1,7 UNION ALL
SELECT '0:34',3,5 UNION ALL
SELECT '0:35',2,6 UNION ALL
SELECT '0:37',1,5 

CREATE TABLE #tmpResults
(
[Time] Time primary key,
[1] FLOAT,
[2] FLOAT,
[3] FLOAT
)

INSERT INTO #tmpResults
SELECT [Time],[1],[2],[3]
FROM @SourceData 
PIVOT ( MAX(value) FOR Device IN ([1],[2],[3])) AS pvt
ORDER BY [Time];

DECLARE @1 FLOAT, @2 FLOAT, @3 FLOAT

UPDATE #tmpResults
SET @1 = [1] = ISNULL([1],@1),
    @2 = [2] = ISNULL([2],@2),
    @3 = [3] = ISNULL([3],@3)


SELECT [Time],
       (SELECT AVG(device)
        FROM   (SELECT [1] AS device
                UNION ALL
                SELECT [2]
                UNION ALL
                SELECT [3]) t) AS [Average value]
FROM   #tmpResults  

DROP TABLE #tmpResults
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...