2009-08-17 3 views
1

Я впервые застрял в некоторых запросах linq, и я борюсь с некоторыми из более сложных. Я создаю запрос для извлечения данных из таблицы для построения графика. Колонны таблиц, которые меня интересуют: Id, Время и Значение.Группировка по диапазонам времени в Linq

Пользователь выберет время начала, время окончания и количество интервалов (точек) на график. Столбец значений будет усреднен для каждого интервала.

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

До сих пор я получил:

var timeSpan = endTime.Subtract(startTime); 
var intervalInSeconds = timeSpan.TotalSeconds/intervals; 

var wattList = (from t in _table 
       where t.Id == id 
        && t.Time >= startTime 
        && t.Time <= endTime 
       group t by intervalInSeconds // This is the bit I'm struggling with 
        into g 
        orderby g.Key 
        select g.Average(a => a.Value)) 
       ).ToList(); 

Любая помощь в группировке более временных диапазонов будет только приветствовать.

ответ

1

Я сделал это сам для точно такой же ситуации, вы описываете.

Для скорости измените таблицу данных datapoints базы данных, чтобы включить целочисленный столбец времени, SecondsSince2000, а затем работал с этим значением в моем запросе LINQ to SQL. SecondsSince2000 является вычисляемый столбец определен как:

datediff(second, dateadd(month,1200,0), DataPointTimeColumn) PERSISTED 

Где DataPointTimeColumn это имя столбца, который хранит время в DataPoint в. Волшебный вызов функции dateadd(month,1200,0) возвращает 2000-01-01 в полночь, поэтому в столбце хранится количество секунд с этого времени.

LINQ к SQL запроса затем сделать гораздо проще и быстрее:

int timeSlotInSeconds = 60; 

var wattList = 
    (from t in _table 
    where t.Id == id 
      && t.Time >= startTime 
      && t.Time <= endTime 
    group t by t.SecondsSince2000 - (t.SecondsSince2000 % timeSlotInSeconds) 
    into g 
    orderby g.Key 
    select g.Average(a => a.Value))).ToList(); 

Если вы не можете изменить вашу базу данных, вы можете сделать это:

var baseTime = new DateTime(2000, 1, 1); 

var wattList = 
    (from t in _table 
    where t.Id == id 
      && t.Time >= startTime 
      && t.Time <= endTime 
    let secondsSince2000 = (int)(t.Time- baseTime).TotalSeconds 
    group t by secondsSince2000 - (secondsSince2000 % timeSlotInSeconds) 
    into g 
    orderby g.Key 
    select g.Average(a => a.Value))).ToList(); 

Запрос будет быть немного медленнее.

+0

Вдохновленный благодарю вас – Magpie

0

Проверьте этот пример, который я написал некоторое время назад. Это похоже на то, что вы пытаетесь сделать, но я не уверен, что это группировка в SQL или .NET.

http://mikeinmadison.wordpress.com/2008/03/12/datetimeround/

+0

Извините, это не поможет – Magpie

0

Может быть, вы можете сделать что-то вроде:

var wattList = (from t in _table 
       where t.Id == id 
        && t.Time >= startTime 
        && t.Time <= endTime 
       ).GroupBy(x => (int) ((x.Time - startTime).TotalSeconds/intervalInSeconds)) 
       .Select(grp => grp.Average(x => x.Value)); 
Смежные вопросы