2012-03-19 23 views
6

Mam dane są rejestrowane co 15 minut w tabelach PowerStringHistorys i PowerCombinerHistorys. Jestem nowy w LINQ i próbuję wymyślić, jak utworzyć zapytanie grupujące moje dane o każdej godzinie, a dla tej godziny średnią bieżącą. Oto co mam tak dalekoGrupowanie według godziny przy użyciu LINQ

 TimeZoneInfo easternZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time"); 
     DateTime UTC_StartingDate = TimeZoneInfo.ConvertTimeToUtc(StartingDate, easternZone); 
     DateTime UTC_EndingDate = TimeZoneInfo.ConvertTimeToUtc(EndingDate, easternZone); 

     var FirstQ = from p in db.PowerStringHistorys 
        join t in db.PowerStrings on p.string_id equals t.id 
        join u in db.PowerCombiners on t.combiner_id equals u.id 
        join s in db.PowerCombinerHistorys on p.recordTime equals s.recordTime 
        where p.recordTime >= UTC_StartingDate 
        where p.recordTime <= UTC_EndingDate 
        select new 
        { 
         Combiner = u.id, 
         Current = p.current, 
         RecordTime = p.recordTime, 
         Voltage = s.voltage 
        }; 

Teraz muszę grupy przez sumator i godzinę, więc mogę średnio prąd i uzyskać kWh dla każdego łączącego za każdą godzinę określonym zakresie dat.

muszę zastosować ten prosty wzór w zapytaniu jakoś: (średnie watów na godzinę)/1000 = kWh

Więc co będę kończyć coś jak poniżej. Każda pomoc będzie bardzo ceniona.

Combiner 1  03/19/2012 1:0:0  1.85 Kwh 
Combiner 1  03/19/2012 2:0:0  1.98 Kwh 
Combiner 1  03/19/2012 3:0:0  2.05 Kwh 
Combiner 1  03/19/2012 4:0:0  2.11 Kwh 
Combiner 1  03/19/2012 5:0:0  2.01 Kwh 
Combiner 1  03/19/2012 6:0:0  1.96 Kwh 
Combiner 1  03/19/2012 7:0:0  1.85 Kwh 
Combiner 2  03/19/2012 1:0:0  1.77 Kwh 
Combiner 2  03/19/2012 2:0:0  1.96 Kwh 
Combiner 2  03/19/2012 3:0:0  2.03 Kwh 
Combiner 2  03/19/2012 4:0:0  2.11 Kwh 
Combiner 2  03/19/2012 5:0:0  2.02 Kwh 
Combiner 2  03/19/2012 6:0:0  1.98 Kwh 
Combiner 2  03/19/2012 7:0:0  1.83 Kwh 
Combiner 3  03/19/2012 1:0:0  1.77 Kwh 
Combiner 3  03/19/2012 2:0:0  1.96 Kwh 
Combiner 3  03/19/2012 3:0:0  2.03 Kwh 
Combiner 3  03/19/2012 4:0:0  2.11 Kwh 
Combiner 3  03/19/2012 5:0:0  2.02 Kwh 
Combiner 3  03/19/2012 6:0:0  1.98 Kwh 
Combiner 3  03/19/2012 7:0:0  1.83 Kwh 

EDIT

Przede był moim oryginalne pytanie. Po pracy z dwiema sugestiami, które otrzymałem, skończyłem z kodem wyświetlanym poniżej. W tej chwili właśnie zwracam daty i łączną liczbę Kwhs do widoku. Mam zamiar rzucić listę stringGroupedKwhlist do HighChart, aby użytkownik mógł wyświetlić i rzucić wyniki pierwszego zapytania do siatki Telerik, aby użytkownik mógł filtrować/sortować/grupować, aby mogli pracować ze szczegółami. Chociaż kod działa i daje oczekiwany wynik, nie jestem pewien, czy jest skuteczny. Ponieważ muszę przechodzić przez foreach, domyślam się, że gdy dostanie on dużo danych, może zwolnić. Czy istnieje bardziej skuteczny sposób radzenia sobie z tym?

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web.Mvc; 
using AESSmart.Models; 

namespace AESSmart.Controllers 
{ 
    public class StringKwh 
    { 
     public int CombinerID; 
     public int StringID; 
     public DateTime Interval; 
     public Double KWH; 

     public StringKwh(int combiner, int stringid, DateTime interval, double kwh) 
     { 
      CombinerID = combiner; 
      StringID = stringid; 
      Interval = interval; 
      KWH = kwh; 
     } 
    } 

    public class HomeController : Controller 
    { 
     private readonly AESSmartEntities db = new AESSmartEntities(); 

     public ActionResult Index() 
     { 
      //REPRESENTS DATE RANGE FOR A FULL DAY 
      DateTime startingDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 0, 0, 1); 
      DateTime endingDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 23, 59, 59); 

      TimeZoneInfo easternZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time"); 
      DateTime utcStartingDate = TimeZoneInfo.ConvertTimeToUtc(startingDate, easternZone); 
      DateTime utcEndingDate = TimeZoneInfo.ConvertTimeToUtc(endingDate, easternZone); 

      var firstQ = from p in db.PowerStringHistorys 
         from s in db.PowerCombinerHistorys 
         join t in db.PowerStrings on p.string_id equals t.id 
         join u in db.PowerCombiners on t.combiner_id equals u.id 
         where p.recordTime == s.recordTime 
         where p.recordTime >= utcStartingDate 
         where p.recordTime <= utcEndingDate 
         select new 
         { 
          Combiner = u.id, 
          StringId = p.string_id, 
          Current = p.current, 
          RecordTime = p.recordTime, 
          Voltage = s.voltage 
         }; 

      var groups = firstQ.ToList().GroupBy(q => new 
               { 
                q.Combiner, 
                q.StringId, 
                Date = q.RecordTime.Date, 
                Hour = q.RecordTime.Hour 
               }); 

      List<StringKwh> stringGroupedKwhlist = new List<StringKwh>(); 

      foreach (var group in groups) 
      { 
       stringGroupedKwhlist.Add(new StringKwh(
             group.Key.Combiner, 
             group.Key.StringId, 
             new DateTime(group.Key.Date.Year, group.Key.Date.Month, group.Key.Date.Day, group.Key.Hour, 0, 0), 
             group.Average(g => g.Voltage * g.Current)/1000d 
             )); 
      } 

      var groupCombiner = stringGroupedKwhlist.GroupBy(q => new { q.CombinerID }); 
      double myTotalKwh = 0; 

      foreach (var combinerGroup in groupCombiner) 
      { 
       myTotalKwh = Math.Round(combinerGroup.Sum(g => g.KWH), 3); 
      } 

      ViewBag.LifeTimeGeneration = myTotalKwh; 
      ViewBag.myUTCStartDate = utcStartingDate; 
      ViewBag.myUTCEndDate = utcEndingDate; 

      return View(); 
     } 

     public ActionResult About() 
     { 
      return View(); 
     } 
    } 
} 

Odpowiedz

11

To może Ci zacząć:

// Group by combiner ID, date, and hour 
var groups = FirstQ.ToList() 
    .GroupBy(q => new 
     { q.Combiner, Date = q.RecordTime.Date, Hour = q.RecordTime.Hour }); 

foreach (var group in groups) 
{ 
    var combinerId = group.Key.Combiner; 
    var interval = new DateTime(group.Key.Date.Year, group.Key.Date.Month, group.Key.Date.Day, group.Key.Hour, 0, 0); 

    // power = voltage * current 
    var kwh = group.Average(g => g.Voltage * g.Current)/1000d; 
} 
+0

Dzięki za odpowiedź. Naprawdę zapomniałem wspomnieć, że muszę również pogrupować według poziomu napisów. Więc dodałem to. Udało mi się sprawić, aby twoje rozwiązanie działało, ale mam problem. Przejrzyj moją zmianę powyżej. – Linger

2

spróbować wymienić select z groupby następująco:

TimeZoneInfo easternZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time"); 
    DateTime UTC_StartingDate = TimeZoneInfo.ConvertTimeToUtc(StartingDate, easternZone); 
    DateTime UTC_EndingDate = TimeZoneInfo.ConvertTimeToUtc(EndingDate, easternZone); 

    var FirstQ = from p in db.PowerStringHistorys 
       join t in db.PowerStrings on p.string_id equals t.id 
       join u in db.PowerCombiners on t.combiner_id equals u.id 
       join s in db.PowerCombinerHistorys on p.recordTime equals s.recordTime 
       where p.recordTime >= UTC_StartingDate 
       where p.recordTime <= UTC_EndingDate 
       group new 
       { 
        Combiner = u.id, 
        Current = p.current, 
        RecordTime = p.recordTime, 
        Voltage = s.voltage 
       } 
       by new 
       { 
        Combiner = u.id, 
        Date = p.RecordTime.Date, 
        Hour = p.RecordTime.Hour 
       }; 
+0

Jeśli to, odczyty zrobić w różnych dniach na tej samej godzinie zostaną zgrupowane razem - musisz również wprowadzić datę do grupy. Ponadto, nie jestem pewien, czy .Hour będzie działać dla wszystkich dostawców danych - może to czknąć, gdy dojdzie do SQL Server. –

+0

Dzięki za odpowiedź. Nie udało mi się sprawić, aby Twoje rozwiązanie działało. Nie wie, co zrobić z q. Chciałbym móc wykonać całą pracę w ramach zapytania. Sądzę, że byłby to najskuteczniejszy sposób radzenia sobie z tym. – Linger

+0

@ToddGrover - Napisałem to trochę zbyt szybko - wziąłem grupę z twojego kodu i dodałem ją do końca 'FirstQ' bez zmiany zmiennej lambda. Zaktualizuję to, aby dopasować obecne zmienne zasięgu. Niestety, myślę, że brakowało mi reszty kodu w zwoju, więc przestanie się to liczyć z ostatnimi projekcjami, które chciałeś; jednakże może to również być osiągnięte za pomocą kontynuacji zapytań (tj. słowa kluczowego 'do') i nieco więcej składni ze zrozumieniem zapytań. Będę aktualizował przynajmniej mam nadzieję, że będzie wolny od błędów składniowych. – devgeezer

Powiązane problemy