【问题标题】:LINQ Select rows with Max of one column and Distinct in anotherLINQ选择一列最大且另一列不同的行
【发布时间】:2013-12-22 17:38:52
【问题描述】:

我正在使用 LINQ to Entities 查询以下 MS-SQL 表:

RateID  RateTypeID  Amount  EffectiveDate   IsRetired
------  ----------  ------  -------------   ---------
1       1           0.565   1/1/2013 0:00   FALSE
2       2           6.000   1/1/2013 0:00   FALSE
3       3           9.000   1/1/2013 0:00   FALSE
4       4           12.000  1/1/2013 0:00   FALSE
5       5           1.500   1/1/2013 0:00   FALSE
6       1           0.550   7/1/2012 0:00   FALSE
7       1           0.495   1/1/2012 0:00   FALSE
8       3           8.000   1/1/2011 0:00   FALSE
9       3           11.000  1/1/2015 0:00   FALSE
10      5           2.000   7/1/2013 0:00   TRUE

我想构建一个函数,该函数将使用 LINQ 返回一个 IQueryable(Of Rate),然后我可以将其加入到其他查询中,以通过 RateTypeID 有效地确定应用于每个项目的当前费率。 IsRetired 必须为 false,我需要最近的行 EffectiveDate

这是我得到的最接近的(LINQPad VB 语句):

Dim dateNow As Date = Date.Now
Dim result = (
    From r In Rates
    Where r.IsRetired = False And r.EffectiveDate <= dateNow
    Group r By r.RateTypeID
    Into rg = Group
    Select New With {
        .cr = rg.OrderByDescending(Function(r) r.EffectiveDate).Take(1)
    }
)
result.Dump()

此查询返回 DbQuery(Of AnonymousType_1(Of IEnumerable(Of Rate)))(一个集合,每个集合都有 1 个评分项),这不是我想要的。

此问答解决了一个非常相似的问题,但使用的是 SQL 而不是 LINQ: How can I SELECT rows with MAX(Column value), DISTINCT by another column in SQL?

我在 vb.net 中进行编码,但也会采用 c# 答案。谢谢!

【问题讨论】:

  • 如果您将最后一行更改为 Select r(而不是 new With.....),查询返回哪种类型?
  • @OmerEldan r 不再在 Group 声明之后的范围内。那时你有DbQuery&lt;Anon&lt;Int32,IEnumerable&lt;Rate&gt;&gt;&gt;。如果你Select rg,你会得到DbQuery&lt;IEnumerable&lt;Rate&gt;&gt;
  • 我遇到的问题是在Group By之后,Rate的集合被RateTypeID分隔,这是MAX排序所必需的,但我需要事后重新组合它们...不知道如何,或者是否有另一种技术可以使用Max(EffectiveDate) 查找整行。

标签: c# vb.net linq linq-to-entities


【解决方案1】:

使用Take() 返回IEnumerable&lt;T&gt;FirstOrDefault() 只返回&lt;T&gt;,所以:

IQueryable<RecentRate> query = from r in Rates
                               where r.IsRetired == false && r.EffectiveDate <= dateNow
                               group r by r.RateTypeID into rg
                               select new RecentRate
                               {
                                 Rate = rg.OrderByDescending(r => r.EffectiveDate).FirstOrDefault()
                               };

这可能有效:

   IQueryable<Rate> query = from r in Rates
                            where r.IsRetired == false && r.EffectiveDate <= dateNow
                            group r by r.RateTypeID into rg
                            select rg.OrderByDescending(r => r.EffectiveDate).FirstOrDefault();

我认为这是 VB 语法

Dim result = (
    From r In Rates
    Where r.IsRetired = False And r.EffectiveDate <= dateNow
    Group r By r.RateTypeID
    Into rg = Group
    Select rg.OrderByDescending(Function(r) r.EffectiveDate).FirstOrDefault()
)

【讨论】:

  • 使用FirstOrDefault 而不是Take 得到DbQuery&lt;Anon&lt;Rate&gt;&gt; 不太成功...但是...
  • 是的,它做到了!我在想同样的事。谢谢!
猜你喜欢
  • 2013-08-15
  • 2020-03-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多