LINQ COUNT на нескольких столбцах - PullRequest
6 голосов
/ 24 января 2009

Если у меня есть таблица со столбцом заголовка и 3-битными столбцами (f1, f2, f3), которые содержат либо 1, либо NULL, как бы я написал LINQ, чтобы вернуть заголовок с счетчиком каждого битового столбца, который содержит 1 ? Я ищу эквивалент этого запроса SQL:

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

Я ищу "лучший" способ сделать это. Версия, которую я придумал, проваливается в таблицу 4 раза, когда вы смотрите на базовый SQL, поэтому он слишком медленный.

Ответы [ 3 ]

4 голосов
/ 25 января 2009

Если вы хотите придерживаться запроса 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 здесь: Стандартные операторы LINQ

2 голосов
/ 24 января 2009

Я думаю, что именно здесь 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");
0 голосов
/ 26 января 2009

Вот решение, которое я придумал. Обратите внимание, что оно близко к решению, предложенному @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 для каждого подсчета. Я делаю подсчет во втором запросе локально.

Это работает, так как я знаю, что первый запрос вернет управляемое количество строк. Если бы он возвращал миллионы строк, мне, вероятно, пришлось бы идти в другом направлении.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...