[英]Complex SQL JOIN Query, min, max and date range
I have the following tables: 我有以下表格:
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 |
+----+--------+
I need to select 2 readings for each meter, the reading with max DateTime and the reading with min DateTime, in addition to the difference between values of the two readings, something like this: 我需要为每个仪表选择2个读数,除了两个读数值之间的差异外,最大日期时间的读数和最小日期时间的读数,如下所示:
+----------+------------+----------------+------------+----------------+------------+
| Meter_Id | MaxReading | MaxReadingTime | MinReading | MinReadingTime | Difference |
+----------+------------+----------------+------------+----------------+------------+
I need a single query to achieve this for all meters within a date range in Entity Framework 我需要一个查询来针对Entity Framework中的日期范围内的所有仪表实现此目的
i was able to get this far (get max and min readings): 我能够做到这一点(获取最大和最小读数):
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;
Using this mockup of your actual schema and data: 使用您的实际模式和数据的此模型:
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 }
};
using this linq query: 使用此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
};
produces this output: 产生以下输出:
[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 }
which should be close to expected result. 应该接近预期的结果。
EDIT: 编辑:
You can considerably simplify the above linq query by making use of the let
clause: 您可以通过使用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
};
Probably not the most efficient, I admit, but that's the quickest I could come up with something without counter-verifying it myself. 我承认,这可能不是最有效的方法,但这是我想出的最快方法,而无需自己对它进行验证。
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
edit: formatting. 编辑:格式化。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.