2017-01-25 22 views
5

Mam tabeli bazy danych, która wygląda tak:C# Query Wybierz pierwszy od wartości zmieniło

Database

teraz. To jest wskaźnik Historii Statusu dla DetektorID 1541.

Chcę wyświetlić tylko jeden wiersz na mojej stronie internetowej. Aby to zrobić, wykonuję następujące zapytanie.

[Query] 
public IQueryable<ScannerStatusHistory> GetScannerStatusHistoryy(int detectorID) 
{ 
    return ObjectContext.ScannerStatusHistories.Where(t => t.DetectorID == detectorID).OrderByDescending(d => d.TimeStamp).Take(1); ; 
} 

Więc co robi, to chwyta najnowszy wiersz (Na podstawie TimeStamp) i pokazuje go.

To da mi wyniki ScannerStatusHistoryID 61.

Ale, co chciałbym mieć, to rząd po raz ostatni wartość został zmieniony.

Jak widać na ScannerStatusHistoryID 54, RC3 miał wartość 4. Następnie na ScannerStatusHistoryID 57 zmieniono z powrotem na 3.

Od tego czasu wartości się nie zmieniły.
To, co chciałbym mieć, to zapytanie, aby pobrać ScannerStatusHistoryID 57. Do zmiany wartości ponownie, a następnie chcę ją pobrać pierwszy z tego.

Jak to osiągnąć? Myślałem o zliczaniu wyników w miejscu, w którym pasowało do ostatniego zapytania. Jednak w tym przykładzie zwróci 7 wyników (od pierwszych 4 są takie same jak w ostatnich 3). I tak nie przyniesie to właściwego rezultatu.

+0

Czy chcesz kontrolować wartość wszystkich kolumn 'hwd' i' RC'? lub 'RC3' wystarczy dla ciebie? –

+0

Zasadniczo, co otrzymam teraz jest najnowszy wynik. Jednak nie muszę tego wiedzieć, ale chciałbym wiedzieć od kiedy to się zmieniło. – Mitch

+1

Od 2012 sql sever ma LEAD, LAG, która daje najprostsze rozwiązanie problemu. Czy usind sql jest bezpośrednio opcją? Linq jak w .Net 4.6.1 nie obsługuje funkcji analitycznych sql. – Serg

Odpowiedz

3

Możesz napisać zapytanie tak, aby go achive:

//return ObjectContext.ScannerStatusHistories.Where(t => t.DetectorID == detectorID).OrderByDescending(d => d.TimeStamp).Take(1); 
    var lastRow = ObjectContext.ScannerStatusHistories.Where(t => t.DetectorID == detectorID).OrderByDescending(d => d.TimeStamp).FirstOrDefault(); 
//Get last changed row 
    if (lastRow != null) 
    { 
     var lastChangeRow = ObjectContext.ScannerStatusHistories 
     .Where(t => t.DetectorID == detectorID 
       && (t.HBD1 != lastRow.HBD1 || t.HBD2 != lastRow.HBD2 || t.HWD1 != lastRow.HWD1 || t.HWD2 != lastRow.HWD2 || t.RC1 != lastRow.RC1 || t.RC2 != lastRow.RC2 || t.RC3 != lastRow.RC3 || t.RC4 != lastRow.RC4)) 
      .OrderByDescending(d => d.TimeStamp) 
      .FirstOrDefault(); 
    //Return next row 
     if (lastChangeRow != null) 
     { 
      return ObjectContext.ScannerStatusHistories 
      .Where(x => lastChangeRow.TimeStamp < x.TimeStamp 
       && x.DetectorID == detectorID) 
      .OrderBy(d => d.TimeStamp) 
      .Take(1); 
     } 
    } 
return ObjectContext.ScannerStatusHistories.Where(t => t.DetectorID == detectorID).OrderBy(d => d.TimeStamp).Take(1); 

Ale maby to lepiej nie tylko dodać wiersz, jeśli nic się nie zmieniło?

+0

Nie możemy tego zrobić (jeśli nic się nie zmieni). System podaje aktualizację co x minut w tym przykładzie. Jednak spróbuję, abyś był rozwiązaniem. – Mitch

+0

@Mitch zawsze można umieścić spust na wstawce w MS SQL, gdzie można sprawdzić, czy wszystko jest takie samo. –

+0

To prawda Teo. Jest to jednak tabela historii. Chcemy uzyskać wszystkie dane wysyłane przez system. Jeśli wysyłamy dane tylko po ich zmianie. Nie wiemy, czy system uruchamia pozostałe x dni. – Mitch