我正在.net环境中使用c#和MVC开发一个web应用程序。数据库是Oracle的,通过DevArt连接器连接到实体框架,我首先从该框架创建了实体数据库。被查询的表有一些数据列和一个日期列。
具体的问题是:用户将为查询输入一个特定的日期,我将获得一个包含该特定日期的元素列表(约10k),并获得它们的归属数据。此外,我还需要列表中每个元素的数据,以备下一个旧日期使用。
注意:这些元素的数据集的日期比用户输入的日期年轻或更老,有时没有更年轻的日期,所以max()或Top2不太容易工作。
这就是我想到的:
var query = context.BsgApo
.Where(
a => ListOfPznsToDate.Contains(a.Pzns)
&& a.Date <= UserDate
&& context.BsgApo.Any(
sub =>
sub.Pzns == a.Pzns &&
sub.Date < a.Date)
&&
context.BsgApo.Any(
negSub => negSub.Pzns == a.Pzns &&
negSub.Date > a.Date &&
negSub.Date < UserDate
) == false
)
.OrderBy(eL => eL.Pzns).ThenBy(eL => eL.Date)
.Select(MapBsgApoToPreisaenderungsErgebnisListe)
.ToList();
首先,我通过元素列表来查询表,其中每个元素都有一个唯一的标识符(pzn),因此我只会得到我感兴趣的元素AND,这些元素的日期等于或小于用户输入的日期。然后我做了一个子查询,因为我想要(可能存在的)较小日期的数据集。如果有,那么我会检查较小的一个和用户输入的日期之间是否没有。
这实际上只起了一半的作用,我错过了一些数据,查询需要几秒钟的时间。
那么,如何以正确快速的方式将下一个较旧日期的数据添加到元素列表中呢?
您应该按pzn
对数据进行分组,并在每个分组中取两个最近的条目。同时筛选具有> 1
条目的组:
var query = context.BsgApo
.Where(a => a.Date <= UserDate)
.GroupBy(eL => eL.Pzns)
.Where(grp => grp.Count() > 1)
.SelectMany(grp => grp.OrderByDescending(eL => eL.Date).Take(2))
.OrderBy(eL => eL.Pzns).ThenBy(eL => eL.Date)
.Select(MapBsgApoToPreisaenderungsErgebnisListe)
.ToList();
(此处省略了一些不相关的部分)