Asp.net 如何编写LINQ查询,将子表过滤到特定时间段,并对子表的结果求和?
如果我必须执行以下操作,那么这是在LINQ中执行左外连接的最有效方法Asp.net 如何编写LINQ查询,将子表过滤到特定时间段,并对子表的结果求和?,asp.net,linq,linq-to-sql,subquery,left-join,Asp.net,Linq,Linq To Sql,Subquery,Left Join,如果我必须执行以下操作,那么这是在LINQ中执行左外连接的最有效方法 按开始日期和结束日期筛选表2 表1中的所有行必须保留,即使表2的筛选没有返回任何行 必须对结果进行分组,以便对表2中的列求和 例如(示例代码变量名因适当的原因更改),假设我有一个包含两个表的数据库。表1列出了带有建筑代码、门ID和当前状态(打开或关闭)的门-建筑代码和门ID是主键。表2列出了所有门的事件(一个事件是打开或关闭)以及时间戳。因此,这些列是建筑代码、门ID、时间戳、打开和关闭。打开和关闭是相应事件列中带有1的整
- 按开始日期和结束日期筛选表2
- 表1中的所有行必须保留,即使表2的筛选没有返回任何行
- 必须对结果进行分组,以便对表2中的列求和
var query =
from doors in Context.Doors
join fevents in
(
from events in db.Events
where events.TimeStamp >= date1 && events.TimeStamp <= date2
select new { events.BuildingCode, events.DoorID, events.TimeStamp, events.Opening, events.Closing }
)
on new { doors.BuildingCode, doors.DoorID } equals { fevents.BuildingCode, fevents.DoorID }
into g1
from c in g1.DefaultIfEmpty()
group c by new
{
doors.BuildingCode,
doors.DoorID,
doors.DoorStatus
} into g2
select new
{
BuildingCode = g2.Key.BuildingCode,
DoorID = g2.Key.DoorID,
Status = g2.Key.DoorStatus
NumOpenings = g2.Sum(i => (i == null ? 0 : i.Opening)),
NumClosings = g2.Sum(i => (i == null ? 0 : i.Closing))
};
var查询=
从上下文中的doors。doors
加入
(
来自db.events中的事件
其中events.TimeStamp>=date1&&events.TimeStamp(i==null?0:i.Opening)),
NumClosings=g2.Sum(i=>(i==null?0:i.Closing))
};
我认为这稍微容易一点
var query =
from doors in Context.Doors
from c in db.Events
.Where(events => doors.BuildingCode == events.BuildingCode)
.Where(events => doors.DoorID == events.DoorID)
.Where(events => events.TimeStamp >= date1 && events.TimeStamp <= date2)
.Select(events => new { events.BuildingCode, events.DoorID, events.TimeStamp, events.Opening, events.Closing })
.DefaultIfEmpty()
group c by new
{
doors.BuildingCode,
doors.DoorID,
doors.DoorStatus
} into g2
select new
{
BuildingCode = g2.Key.BuildingCode,
DoorID = g2.Key.DoorID,
Status = g2.Key.DoorStatus
NumOpenings = g2.Sum(i => (i == null ? 0 : i.Opening)),
NumClosings = g2.Sum(i => (i == null ? 0 : i.Closing))
};
var查询=
从上下文中的doors。doors
从c到db.Events
.Where(events=>doors.BuildingCode==events.BuildingCode)
.Where(events=>doors.DoorID==events.DoorID)
.Where(events=>events.TimeStamp>=date1&&events.TimeStamp new{events.BuildingCode,events.DoorID,events.TimeStamp,events.Opening,events.Closing})
.DefaultIfEmpty()
c组由纽约
{
doors.BuildingCode,
门,门牌,
门,门的状态
}进入g2
选择新的
{
BuildingCode=g2.Key.BuildingCode,
DoorID=g2.Key.DoorID,
状态=g2.Key.door状态
NumOpenings=g2.Sum(i=>(i==null?0:i.Opening)),
NumClosings=g2.Sum(i=>(i==null?0:i.Closing))
};
来自@Encalucci的答案帮助我想出了一个稍微不同的解决方案,我认为它更具可读性,尽管效率可能更低
var query =
from doors in Context.Doors
from events in doors.Events
.Where(i => i.TimeStamp >= date1 && i.TimeStamp <= date2)
.DefaultIfEmpty()
group new { doors, events }
by doors into g
select new
{
BuildingCode = g.Key.BuildingCode,
DoorID = g.Key.DoorID,
Status = g.Key.DoorStatus,
NumOpenings = g.Sum(i => (i.events == null ? 0 : i.events.Opening)),
NumClosings = g.Sum(i => (i.events == null ? 0 : i.events.Closing))
};
var查询=
从上下文中的doors。doors
来自门中的事件。事件
。其中(i=>i.TimeStamp>=date1&&i.TimeStamp(i.events==null?0:i.events.Opening)),
NumClosings=g.Sum(i=>(i.events==null?0:i.events.Closing))
};
请注意,按日期筛选的替代方法将直接在求和函数中,如下所示,但效率要低得多,因为将从数据库检索所有记录,然后在本地进行筛选
...
//from events in doors.Events
// .Where(i => i.TimeStamp >= date1 && i.TimeStamp <= date2)
// .DefaultIfEmpty()
from events in doors.Events
.DefaultIfEmpty()
...
NumOpenings = g.Sum(i => (i.events == null ? 0 : (i.events.Timestamp >= date1 && i.events.TimeStamp <= date2) ? i.events.Opening : 0)),
NumClosings = g.Sum(i => (i.events == null ? 0 : (i.events.Timestamp >= date1 && i.events.TimeStamp <= date2) ? i.events.Closing : 0))
...
。。。
//来自门中的事件。事件
//。其中(i=>i.TimeStamp>=date1&&i.TimeStamp(i.events==null?0:(i.events.TimeStamp>=date1&&i.events.TimeStamp)(i.events==null?0:(i.events.Timestamp>=date1&&i.events.Timestamp感谢您的回答@aducci。非常有用。它让我以不同的方式思考了这个问题。我发布了稍微不同的答案,作为其他人的参考。