【问题标题】:Get max & min from Entity Framework, in one query and with best query possible从实体框架中获取最大值和最小值,在一个查询中并尽可能进行最佳查询
【发布时间】:2022-01-27 17:33:47
【问题描述】:

我知道this 的问题,但我想做的是获得接近这个生成的 SQL 的东西:

select MAX(Column), MIN(Column) from Table WHERE Id = 1

当我尝试这个时:

var query = from d in db.Table
            where d.Id == 1
            select new
            {
                min = db.Table.Max(s => s.Column),
                max = db.Table.Min(s => s.Column)
            };

生成的sql如下所示:

SELECT 
    [Extent1].[Id] AS [Id], 
    [GroupBy1].[A1] AS [C1], 
    [GroupBy2].[A1] AS [C2]
    FROM   [dbo].[Table] AS [Extent1]
    CROSS JOIN  (SELECT 
        MAX([Extent2].[Column]) AS [A1]
        FROM [dbo].[Table] AS [Extent2] ) AS [GroupBy1]
    CROSS JOIN  (SELECT 
        MIN([Extent3].[Column]) AS [A1]
        FROM [dbo].[Table] AS [Extent3] ) AS [GroupBy2]
    WHERE ([Extent1].[Id] = 1) AND (1 IS NOT NULL)

我也试过这个:

var query = from d in db.Table
           where d.Id == 1
           group d by d.Id into grp
           let min = grp.Min(s => s.Column)
           let max = grp.Max(s => s.Column)
           select new { min, max };

这给出了这个:

SELECT 
    [Project2].[Id] AS [Id], 
    [Project2].[C1] AS [C1], 
    [Project2].[C2] AS [C2]
    FROM ( SELECT 
        [Project1].[C1] AS [C1], 
        [Project1].[Id] AS [Id], 
        (SELECT 
            MAX([Extent2].[Column]) AS [A1]
            FROM [dbo].[Table] AS [Extent2]
            WHERE ([Extent2].[Id] = 1) AND (1 IS NOT NULL) AND ([Project1].[Id] = [Extent2].[Id])) AS [C2]
        FROM ( SELECT 
            [GroupBy1].[A1] AS [C1], 
            [GroupBy1].[K1] AS [Id]
            FROM ( SELECT 
                [Extent1].[Id] AS [K1], 
                MIN([Extent1].[Column]) AS [A1]
                FROM [dbo].[Table] AS [Extent1]
                WHERE ([Extent1].[Id] = 16) AND (16 IS NOT NULL)
                GROUP BY [Extent1].[Id]
            )  AS [GroupBy1]
        )  AS [Project1]
    )  AS [Project2]

它们都有效,并且性能影响可能可以忽略不计,因此主要是美观:
这两个生成的查询都伤害了我的眼睛。

【问题讨论】:

  • group d by true into grp怎么办?
  • @Magnus,差别不大/没有差别

标签: c# linq entity-framework generated-sql


【解决方案1】:

尝试删除 let 语句 - 以下会产生预期结果:

var q = from d in db.Table
        where d.Id == 1
        group d by d.Id into g
        select new
        {
            Id = g.Key, // shown for illustrative purposes
            ColumnMin = g.Min( gi => gi.Column ),
            ColumnMax = g.Max( gi => gi.Column )
        };

var result = q.SingleOrDefault();

生成的 SQL:

SELECT 
    [GroupBy1].[K1] AS [Id],
    [GroupBy1].[A1] AS [C1], 
    [GroupBy1].[A2] AS [C2]
    FROM ( SELECT 
        [Extent1].[Id] AS [K1], 
        MIN([Extent1].[Column]) AS [A1], 
        MAX([Extent1].[Column]) AS [A2]
        FROM [dbo].[Table] AS [Extent1]
        WHERE 1 = [Extent1].[Id]
        GROUP BY [Extent1].[Id]
    )  AS [GroupBy1]

【讨论】:

    【解决方案2】:

    8 年后,我们到了!但还是有答案!

    db.Table
      .Where(d => d.Id == 1)
      .GroupBy(_ => 1,
        (_, records) => new
                        {
                            Max = records.Max(r => r.Column),
                            Min = records.Min(r => r.Column)
                         });
    

    这会导致:

    SELECT MAX([o].[Column]) AS [Max], MIN([o].[Column]) AS [Min]
    FROM [Table] AS [o]
    WHERE [o].[Id] = 1
    GO
    

    请注意,在“Group by 1”中,1 与查询中的 ID 无关!

    【讨论】:

      【解决方案3】:
      var query = from d in db.Table
                  where d.Id == 1
                  select
                  {     
                      d.Max(t =>t.yourColName),  
                      d.Min(t =>t.yourColName)  
                  };
      

      【讨论】:

      • 在上面的代码中,首先选择与 d.Id==1 关联的记录,然后根据您的要求选择最大和最小列
      • 我不是 OP,只是就如何改进答案提供建议,而不是在没有解释的情况下在答案中添加代码(对于 OP 和未来寻找答案的人)跨度>
      • 很好,只是它不能编译。
      猜你喜欢
      • 2022-11-25
      • 1970-01-01
      • 2018-10-21
      • 2017-01-20
      • 2018-11-26
      • 2019-03-13
      • 1970-01-01
      • 2020-03-29
      • 2015-02-03
      相关资源
      最近更新 更多