【问题标题】:LINQ COUNT on multiple columns多列上的 LINQ COUNT
【发布时间】:2009-01-23 22:11:16
【问题描述】:

如果我有一个包含 1 或 NULL 的标题列和 3 位列(f1、f2、f3)的表,我将如何编写 LINQ 以返回包含 1 的每个位列的计数的标题?我正在寻找这个 SQL 查询的等价物:

SELECT title, COUNT(f1), COUNT(f2), COUNT(f3) FROM myTable GROUP BY title

我正在寻找“最好”的方式来做到这一点。我想出的版本在看底层 SQL 时会掉表 4 次,所以太慢了。

【问题讨论】:

    标签: .net sql linq linq-to-sql


    【解决方案1】:

    如果您想坚持使用 LINQ 查询并使用匿名类型,则查询可能如下所示:

     var query = 
          from r in ctx.myTable
          group r by r.title into rgroup
          select new
          {
              Title = rgroup.Key,
              F1Count = rgroup.Count(rg => rg.f1 == true),
              F2Count = rgroup.Count(rg => rg.f2 == true),
              F3Count = rgroup.Count(rg => rg.f3 == true)
          };
    

    诀窍是要识别出您想要计算真实字段的数量(它被映射为可为空的布尔值),您可以使用 Count 运算符和谓词来做到这一点。有关 LINQ 组运算符的更多信息,请点击此处:The Standard LINQ Operators

    【讨论】:

    • 这是我最初想出的解决方案,但生成的查询使用子选择来生成每个单独的计数。在有 50 万行(无索引)的表上,此版本需要 7 秒,而具有 3 个 COUNT 的正确 SQL 是即时的。
    【解决方案2】:

    我认为这就是 LINQ 失败的地方。如果你想要高效地使用 SQL,如果你想要漂亮的代码,使用 LINQ。

    您总是可以直接执行查询,因为您已经知道 SQL。

    class TitleCount {
        public string Title;
        public int Count1;
        public int Count2;
        public int Count3;
    }
    
    DataContext dc = new DataContext("Connection string to db");
    
    IEnumerable<TitleCount> query = dc.ExecuteQuery<TitleCount>(
        @"SELECT title, 
                 COUNT(f1) as Count1, 
                 COUNT(f2) as Count2, 
                 COUNT(f3) as Count3 
           FROM myTable GROUP BY title");
    

    【讨论】:

      【解决方案3】:

      这是我想出的解决方案。请注意,它与@OdeToCode 提出的解决方案很接近(但在 VB 语法中),但有一个主要区别:

      Dim temp = _
          (From t In context.MyTable _
           Group t.f1, t.f2, t.f3 By t.title Into g = Group _
           Select title, g).ToList
      
      Dim results = _
          From t In temp _
          Select t.title, _
              f1_count = t.g.Count(Function(x) If(x.f1, False)), _
              f2_count = t.g.Count(Function(x) If(x.f2, False)), _
              f3_count = t.g.Count(Function(x) If(x.f3, False))
      

      第一个查询进行分组,但 ToList 从服务器获取分组数据。在此处消除计数可防止生成的 SQL 语句为每个计数生成子 SELECT。我在本地进行第二个查询中的计数。

      这是可行的,因为我知道第一个查询将返回可管理的行数。如果它返回数百万行,我可能不得不转向另一个方向。

      【讨论】:

      • 不要将它用于大型数据集!请不要将其复制并粘贴到您的应用程序中。这个答案应该有一个巨大的警告。
      猜你喜欢
      • 2022-08-18
      • 1970-01-01
      • 1970-01-01
      • 2013-09-28
      • 2019-07-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多