我正在尝试编写一个LINQ查询,该查询将获取所有记录并按Period
即Sep-18
进行分组,然后返回周期内编号为Version
最高的记录。例如,如果我的periodNames
列表中包含三个句点,则输出列表应返回:
Sep-18
版本:1、2、3(返回版本3的记录)
Oct-18
版本:1、2(返回带有版本2的记录)
Nov-18
版本:1、2、3、4(返回带有版本4的记录)
这是我到目前为止编写的查询:
var previousStatements = _context.Statements.Where(x => periodNames.Contains(x.Period) &&
x.Version == _context.Statement.Max(y => y.Version)).toList();
如何使它适应以上规范?谢谢
答案 0 :(得分:1)
您可以使用GroupBy
来对语句进行分组,使用Max
来查找最大值,例如
var previousStatements = _context.Statements.Where(x => periodNames.Contains(x.Period))
.GroupBy(x => x.Period)
.Select(x => new { Period = x.Key, MaxVersion = x.Max(y => y.Version))
.ToList();
上面的代码仅返回“期间”和最大版本号。如果您需要每个时期的版本号最高的记录,则可以使用以下方法:
var previousStatements = (ctx.Items.Where(x => periodNames.Contains(x.Period))
.GroupBy(x => x.Period)
.ToArray())
.Select(x => x.OrderByDescending(y => y.Version).First())
.ToList();
请注意,上面的代码首先使用对ToArray
的调用来将GroupBy查询发送到数据库。从返回的组中,然后在内存中检索每个期间的最高版本号的行。
答案 1 :(得分:1)
尝试使用GroupBy,然后按降序排列以获得最大版本:
_context.GroupBy(f => f.Period).Select(f=>f.OrderByDescending(r=>r.Version).First()).ToList();
答案 2 :(得分:1)
如果您编写了适当的要求,我想您会知道解决方案的
您写道:
...按时段将它们分组,即Sep-18,然后返回时段内的最高版本号
您的示例未返回最高版本号,而是具有最高版本号的行,因此,我们假设这是您想要的:
从一系列语句中,将这些语句分为
Period
相等的语句组,然后从每个组中返回VersionNumber
最大的语句。
如果同一期间中的两个语句具有相同的VersionNumber,则您尚未定义所需的内容。假设您认为这种情况不会发生,那么您不必担心在这种情况下会返回哪一个。
因此,您有Statements
的序列,其中每个Statement
都有一个Period
和一个VersionNumber
。
正式地,您尚未定义Period
和VersionNumber
的类,我们对它们的唯一了解是,您有一些代码可以确定两个Periods
是否相等,然后您可以决定哪个VersionNumber
更大。
IEqualityComparer<Period> periodComparer = ...
IComparer<VersionNumber> versionComparer = ...
如果Period
与DateTime
类似,而VersionNumber
与int类似,则这些比较器很容易,否则您将需要编写比较器。
根据您的要求,代码很简单:
在每个具有此期间的语句组中,仅保留具有最高VersionNumber的语句。
IEnumerable<Statement> statements = ...
var latestStatementsWithinAPeriod = statements
.GroupBy(statement => statement.Period, // group by same value for Period
(period, statementsWithThisPeriod) =>
// From every group of statements keep only the one with the highest VersionNumber
// = order by VersionNumber and take the first
statementWithThisPeriod
.OrderByDescending(statement => statement.VersionNumber,
versionComparer)
.FirstOrDefault(),
periodComparer);
再次:如果可以使用默认比较器来确定两个Period何时相等以及哪个VersionNumber较大,则无需添加比较器。
SorBy的缺点是第3个元素和第4个元素等也会排序,而您只需要第一个元素,即具有最大VersionNumber的元素。
这可以通过使用不太常用的Aggregate来优化:
(period, statementsWithThisPeriod) => statementWithThisPeriod.Aggregate(
(newestStatement, nextStatement) =>
(versionComparer.Compare(newestStatement.VersionNumber, nextStatement.VersionNumber) >=0 ) ?
newestStatement :
nextStatement)
这将把第一个语句作为newestStatement(=直到现在这是具有最高版本号的语句)。第二个元素将放在nextStatement中。将比较这两个语句,如果nextStatement的VersionNumber大于newestStatement,则nextStatement将被认为是较新的,因此将替换newestStatement。聚合的结尾将返回newestStatement
答案 3 :(得分:0)
您可以尝试使用GroupBy和OrderByDescending,然后选择第一个。
var statements = _context.Statements
.Where(x => periodNames.Contains(x.Period))
.GroupBy(g => g.Period)
.Select(s => s.OrderByDescending(o => o.Version)
.FirstOrDefault()).ToList();