2009-03-17 1 views
1

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

Если бы я хотел посмотреть, скажем, в прошлом месяце, большое количество точек данных создало бы уродливый отчет с нечитаемыми метками на оси 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 
); 
+0

Вы пытаетесь сгруппировать по определенному интервалу времени? –

+0

Произвольный временной интервал. Я могу решить, что 20 точек данных на диаграмме идеальны, поэтому я хочу уменьшить количество данных X до 20. – spoulson

ответ

0

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

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

1

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

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

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

0

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

КИ, вот решение, чтобы получить п агрегатов (насколько есть данные в каждом куске времени):

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)[email protected])/(@period/@points),0,1) 
from perftable 
group by 
round((cast(time as float)[email protected])/(@period/@points),0,1) 

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

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

+0

Я смог это сделать, но то, что я хочу сделать, сводится к совокупности не более * n * данные точки. Пользователь, создающий отчет, не захочет возиться с интервалами агрегирования, чтобы получить полезную диаграмму отчета. – spoulson

0

Предположим, что мы хотим иметь 3 раза и среднее значение «значение» в этом диапазоне.

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

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

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

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

Группы по часам:

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 

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