[英]Entity Framework Conditional Selection
编号1 | 编号2 | 日期 | State |
---|---|---|---|
1个 | 1个 | 2022-03-14 | 失败的 |
1个 | 1个 | 2022-03-15 | 成功 |
鉴于上面的数据库表,我正在尝试编写 EF 查询,我们在其中显示每个 Id Id2 组合的最新记录,但失败将永远列出。 仅当成功发生在上周时才会包括在内。
我认为我正在努力解决的部分是,如果给定的 Id Id2 组合存在失败,但未来会成功,则不应返回失败。
关于从哪里开始的任何建议? 之前的尝试试图做一个
.Where(x => x.state == 'Failed' || x.CreatedOn > DateTime.Now.AddDays(-7)
但是列出了 10 天前的失败和 9 天前的成功。 (这个案例应该不会返回任何东西,因为成功是在一个多星期前)
基本上都失败了,除了后来成功的 UNION 成功持续了 2 天。 这可能吗? 我从来没有在两张桌子之间的 linq 上花这么长时间。
先问一个问题:如果最新的state失败了,是不是只想报上次成功之后的失败? 换句话说,对于序列 {Failure, Failure, Success, Failure, Failure} 你只想报告最后两个失败吗? 我会假设,是的。
在我看来,您首先需要按 Id2 分组并为每个组计算两件事:
从那里,您可以 select 组的成员,其中:
就像是
Data
.Where(r => r.CreatedOn >= DateTime.Now.AddDays(-7))
.GroupBy(r => r.Id2)
.SelectMany(grp => new {
var latestState = grp
.OrderByDescending(r => r.CreatedOn)
.Select(r => r.State)
.First(),
var latestSuccessDate = grp
.OrderByDescending(r => r.CreatedOn)
.Where(r => r.State = 'Success')
.Select(r => r.CreatedOn)
.FirstOrDefault();
return grp
.Where(r =>
(latestState == "Success" && r.CreatedOn == latestSuccessDate)
|| (r.State == "Failure" && (latestSuccessDate == null || r.CreatedOn > latestSuccessDate))
);
});
免责声明 - 以上未经检查,在语法上可能不是 100% 正确,但传达了我的想法。 我确信还有优化的空间,例如预先订购每个组的成员。
我希望上面的代码将执行 memory 中的大部分工作。我不确定是否可以将其编码为将转换为服务器端 SQL 查询的形式。 比我有更多技能的人可能会提供解决方案。 目标是生成如下内容:
SELECT D.*
FROM (
-- Select latest state per group
) LS
LEFT JOIN (
-- Select the latest success date per group
) LSD
ON LSD.Id2 = LS.Id2
JOIN DATA D
ON D.Id2 = LS.Id2
WHERE -- Other conditions
我不确定这是否可以转换为 EF 查询,但我认为我会发布它以防万一(或者万一它可以提供一些灵感)。 这是一个 Linq 到对象的方法,应该产生所需的 output。
如果你的class定义如下:
public class Item
{
public int Id1 { get; set; }
public int Id2 { get; set; }
public DateTime Date { get; set; }
public State State { get; set; }
}
public enum State
{
Undefined,
Success,
Failed
}
并且您的项目存储在Item
集合中,您可以:
Id1
和Id2
对项目进行分组Date
值的一项(使用.MaxBy()
)
.MaxBy( * )
也可以替换为.OrderByDescending( * ).First()
)Id1
和Id2
项目集合以仅保留具有State = Failed
或不少于一周的项目对于项目集合List<Item> items
,它可以实现如下:
List<Item> result = items
.GroupBy(item => ( item.Id1, item.Id2 ))
.Select(gr => gr.MaxBy(item => item.Date))
.Where(item =>
item.State == State.Failed ||
item.Date > DateTime.Now.AddDays(-7))
.ToList();
示例小提琴在这里。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.