Как объединить строки, чтобы уменьшить разрешение данных в запросе SQL? - PullRequest
1 голос
/ 17 марта 2009

Я работаю с базой данных MSSQL 2000, содержащей большие объемы данных Windows Permon, собранных для всех серверов в среде. Я использую SSRS 2005 для создания настраиваемой диаграммы отчетов для визуализации метрик с течением времени.

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

Я пытался создать запрос с помощью причудливых предложений GROUP BY, но не смог создать что-то, что выполняется. Я подумал, что это должно быть обычной задачей для SQL, но я не нашел ответов в Интернете.

Структура таблицы в основном выглядит ниже. На самом деле это база данных MOM 2005 OnePoint, но я думаю, что приложение не имеет значения.

CREATE TABLE PerfTable (
   [time] datetime,
   value float,
   Server nvarchar(356),
   ObjectName nvarchar(225),
   CounterName nvarchar(225),
   InstanceName nvarchar(225),
   Scale float
);

Ответы [ 5 ]

1 голос
/ 17 марта 2009

Возможно, стоило бы создать View для просмотра данных за месяцы и работы с SQL, чтобы уменьшить объем данных.

Затем вы можете запустить отчет из этого представления.

Кроме того, возможно, стоит дать нам представление о структуре таблицы и SQL, который вы в настоящее время используете для получения результатов.

0 голосов
/ 27 августа 2009

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

Группировка по часам:

select
   dateadd(hh, datediff(hh, '1970-01-01', [time]), '1970-01-01'),
   Server, ObjectName, CounterName, InstanceName, avg(value)
from PerfTable
group by
   dateadd(hh, datediff(hh, '1970-01-01', [time]), '1970-01-01'),
   ComputerName, ObjectName, CounterName, InstanceName
order by
   dateadd(hh, datediff(hh, '1970-01-01', [time]), '1970-01-01') desc,
   ObjectName, CounterName, InstanceName, ComputerName

Это просто не решает проблему уменьшения до n точек данных.

0 голосов
/ 17 марта 2009

Скажем, мы хотим, чтобы у нас было 3 временных интервала и среднее значение "value" в этом диапазоне.

Сначала мы определяем периоды .. начало-конец, начало-конец, начало-конец и т. Д. Это вы можете сделать в своем собственном коде, поэтому я использую параметры.

В этом примере мы также группируем по «серверу», но вы можете добавить дополнительные столбцы или удалить их.

DECLARE @startdate1 as DateTime
DECLARE @enddate1 as DateTime
DECLARE @startdate2 as DateTime
DECLARE @enddate2 as DateTime
DECLARE @startdate3 as DateTime
DECLARE @enddate3 as DateTime
SELECT 
  CASE WHEN time >= @startdate1 AND time < @enddate1 THEN 'PERIOD1'
    ELSE CASE WHEN time >= @startdate2 AND time < @enddate2 THEN 'PERIOD2'
     ELSE CASE WHEN time >= @startdate3 AND time < @enddate3 THEN 'PERIOD3' 
     END 
    END
  END as Period,
  AVG(p.[value]),
  p.[Server]
FROM PerfTable p
GROUP BY 
  CASE WHEN time >= @startdate1 AND time < @enddate1 THEN 'PERIOD1'
    ELSE CASE WHEN time >= @startdate2 AND time < @enddate2 THEN 'PERIOD2'
     ELSE CASE WHEN time >= @startdate3 AND time < @enddate3 THEN 'PERIOD3' 
     END 
    END
  END,
  p.[Server]
0 голосов
/ 17 марта 2009

Вы можете использовать функцию DATEPART для получения фрагментов данных, отфильтрованных по определенному дню, часу или минуте (или нескольким другим). Вы должны быть в состоянии сгруппировать их и получить необходимые вам средние / совокупные значения.

Хорошо, вот решение для получения n агрегатов (если есть данные в каждом отрезке времени):

declare @points as int
declare @start as float
declare @period as float

set @points = 20

select 
@start=cast(min(time) as float), 
@period=cast(max(time)-min(time) as float) 
from perftable

select avg(value),
round((cast(time as float)-@start)/(@period/@points),0,1)
from perftable
group by
round((cast(time as float)-@start)/(@period/@points),0,1)

@ points - это число агрегатов, которое вы хотите получить. @start - это время первой записи в отчете, переданной для плавания @period - разница между начальной и конечной датами в отчете

Остальное - линейное масштабирование дат до диапазона [0; @points], усечение результатов до целых чисел и группирование по усеченным результатам.

0 голосов
/ 17 марта 2009

Вам действительно нужно уменьшить количество записей, возвращаемых из SQL, или просто данные, представленные диаграммой?

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

...