[英]Complex SQL JOIN Query, min, max and date range
我有以下表格:
Readings:
+----+---------------------+-------+----------+
| Id | TimestampLocal | Value | Meter_Id |
+----+---------------------+-------+----------+
| 1 | 2014-08-22 18:05:03 | 50.5 | 1 |
| 2 | 2013-08-12 14:02:09 | 30.2 | 1 |
+----+---------------------+-------+----------+
Meters:
+----+--------+
| Id | Number |
+----+--------+
| 1 | 32223 |
+----+--------+
我需要為每個儀表選擇2個讀數,除了兩個讀數值之間的差異外,最大日期時間的讀數和最小日期時間的讀數,如下所示:
+----------+------------+----------------+------------+----------------+------------+
| Meter_Id | MaxReading | MaxReadingTime | MinReading | MinReadingTime | Difference |
+----------+------------+----------------+------------+----------------+------------+
我需要一個查詢來針對Entity Framework中的日期范圍內的所有儀表實現此目的
我能夠做到這一點(獲取最大和最小讀數):
SELECT
tt.*
FROM Readings tt
INNER JOIN
(
SELECT
Meter_Id,
MAX(TimeStampLocal) AS MaxDateTime,
MIN(TimeStampLocal) AS MinDateTime
FROM Readings
where TimeStampLocal > '2014-12-08'
GROUP BY Meter_Id
) AS groupedtt
ON (tt.Meter_Id = groupedtt.Meter_Id) AND
(tt.TimeStampLocal = groupedtt.MaxDateTime or tt.TimeStampLocal = groupedtt.MinDateTime)
order by Meter_Id;
使用您的實際模式和數據的此模型:
class Reading
{
public int Id { get; set; }
public DateTime TimestampLocal { get; set; }
public double Value { get; set; }
public int Meter_Id { get; set; }
}
List<Reading> Readings = new List<Reading>()
{
new Reading { Id = 1, TimestampLocal = new DateTime(2014, 8, 22), Value = 50.5, Meter_Id = 1 },
new Reading { Id = 2, TimestampLocal = new DateTime(2013, 8, 12), Value = 30.2, Meter_Id = 1 },
new Reading { Id = 3, TimestampLocal = new DateTime(2013, 9, 12), Value = 35.2, Meter_Id = 1 }
};
使用此linq查詢:
var q = from r in Readings
group r by r.Meter_Id into rGroup
select new
{
Meter_Id = rGroup.Key,
MaxReading = rGroup.OrderByDescending(x => x.TimestampLocal).First().Id,
MaxReadingTime = rGroup.OrderByDescending(x => x.TimestampLocal).First().TimestampLocal,
MinReading = rGroup.OrderBy(x => x.TimestampLocal).First().Id,
MinReadingTime = rGroup.OrderBy(x => x.TimestampLocal).First().TimestampLocal,
Difference = rGroup.OrderByDescending(x => x.TimestampLocal).First().Value -
rGroup.OrderBy(x => x.TimestampLocal).First().Value
};
產生以下輸出:
[0] = { Meter_Id = 1, MaxReading = 1, MaxReadingTime = {22/8/2014 12:00:00 πμ},
MinReading = 2, MinReadingTime = {12/8/2013 12:00:00 πμ}, Difference = 20.3 }
應該接近預期的結果。
編輯:
您可以通過使用let
子句來大大簡化上面的linq查詢:
var q = from r in Readings
group r by r.Meter_Id into rGroup
let MaxReading = rGroup.OrderByDescending(x => x.TimestampLocal).First()
let MinReading = rGroup.OrderBy(x => x.TimestampLocal).First()
select new
{
Meter_Id = rGroup.Key,
MaxReading = MaxReading.Id,
MaxReadingTime = MaxReading.TimestampLocal,
MinReading = MinReading.Id,
MinReadingTime = MinReading.TimestampLocal,
Difference = MaxReading.Value - MinReading.Value
};
我承認,這可能不是最有效的方法,但這是我想出的最快方法,而無需自己對它進行驗證。
SELECT m.Id AS Meter_Id, MaxReading, MaxReadingTime, MinReading, MinReadingTime, (MaxReading - MinReading) AS Difference
FROM Meters m
CROSS APPLY (SELECT MIN(Value) MinReading, TimestampLocal AS MinReadingTime FROM Readings WHERE Meter_Id = m.Id) min
CROSS APPLY (SELECT MAX(Value) MaxReading, TimestampLocal AS MaxReadingTime FROM Readings WHERE Meter_Id = m.Id) max
編輯:格式化。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.