【问题标题】:LINQ version of Where In Subquery With Max and Group By带有 Max 和 Group By 的子查询中的 LINQ 版本
【发布时间】:2014-11-01 08:38:34
【问题描述】:

您将如何使用 LINQ to Entities 来完成以下查询。

SELECT [id] ,[value1], [value2], [dateValue]
FROM table
WHERE dateValue IN (
    SELECT MAX(dateValue)
    FROM table
    GROUP BY id
)

表中有多个具有相同 id 的条目,所以我只想要每个 id 具有最大日期值的一个。此外,dateValue 包含一个精确到毫秒的时间分量,并且不会重复。

我知道 LINQ To Entities 不支持 IN 关键字,但是我了解到您仍然可以通过使用 context.tableName.Any() 方法或在 Select 部分中添加查询来处理子查询。

Using context = ContextProvider.GetContext()
    Dim table = context.tableName

    Dim query = _
        From rows In table _
        Select New ClassName With _
               { _
                   .Id = rows.Id, _
                   .Value1 = rows.Value1, _
                   .Value2 = rows.Value2, _
                   .DateValue = rows.DateValue _
               }

    Return query.ToList()
End Using

鉴于上述情况,我不确定查询中是否应该有 Where table.Any(... 或 Select 中的 .DateValue = subquery 以获得我想要的。在任何一种情况下,我都不确定如何格式化表达式。

【问题讨论】:

  • 如果只需要 MAX(dateValue),为什么要在子查询中按 id 分组?您是否希望每个 ID 的前 1 条记录具有 MAX(dateValue)?那么sql查询不正确。
  • 是的,有多个条目具有相同的 ID,我只希望每个 ID 有 1 个条目,该 ID 的最大日期。
  • 你的表的主键是什么?
  • 主键为id和mainDate,其中第二个未使用。
  • 我删除了 DISTINCT 关键字,因为经过更多测试,我相信它对查询没有任何作用。

标签: sql vb.net entity-framework linq-to-entities where-in


【解决方案1】:

实际上你的 sql 已经不正确了,因为除了日期之外,子查询和主查询之间没有任何关系。如果您的 ID 的 dateValue 是另一个 ID 的 max-dateValue,那么您会得到带有错误 ID 的记录。

因此,如果您想要每个 ID 具有最大日期的记录,我会这样做:

WITH CTE AS
(
    SELECT rn = ROW_NUMBER() OVER (PARTITION BY [id] ORDER BY [dateValue] DESC),
          [id] ,[value1], [value2], [dateValue]
    FROM table
)
SELECT [id] ,[value1], [value2], [dateValue]
FROM CTE
WHERE RN = 1

在 LINQ 中这应该可以工作(我对 Linq-To-Entities 不太熟悉):

Dim query = From row In table
            Group row By row.Id into idGrp
            Let MaxDatePerID = idGrp.Max(Function(r) r.DateValue)
            From idRow In idGrp
            Where idRow.DateValue = MaxDatePerID 
            Select New ClassName With 
            { 
               .Id = idRow.Id, 
               .Value1 = idRow.Value1, 
               .Value2 = idRow.Value2, 
               .DateValue = idRow.DateValue 
            }

【讨论】:

  • 我已经对表运行了常规 SQL 查询,它确实给了我正确的结果。我什至对表中的每个 ID 使用 SELECT MAX(dateValue) FROM table Where id = ... 单独检查了日期,并且日期匹配。我不是说你的方法不对,我试一试,但我的 SQL 语句似乎不像你说的那样不对。
  • @JeremyK:考虑这 3 行:1) ID=1,DateValue=2014/9/7 2) ID=1,DateValue=2014/9/8 3) ID=2,DateValue=2014/9/7。现在,即使不是此 ID 的最大日期,您也可以获得第一条记录,因为该日期是另一个 ID 的最大日期。
  • 哦,我明白了。对于某些人来说,这可能是一个合理的担忧。我永远不会遇到这种情况,因为日期是一个 dateTime 值,精确到毫秒。我应该更清楚这一点。对不起。
  • @JeremyK:错误仍然是错误,即使您不太可能注意到它。通常这些是最令人讨厌的问题,因为您从未意识到它们。
  • 确实如此。我已经验证了 SQL 确实可以正常工作。尽管我还必须将WHERE NOT dateValue IS NULL 包含在第一部分中。尚未验证 LINQ,但看起来您得到了正确的答案。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多