2016-04-04 3 views
3

Я хотел бы понять, что я делаю неправильно с моим запросом GROUP BY в Linq. Я пробовал много примеров (т. Е. Linq with group by having count), но я все еще получаю больше результатов (как пропускается WHERE). Мой код выглядит так:LINQ with GROUP BY and HAVING COUNT

var test = session.Query<SomeClass>() 
        .GroupBy(c => new { c.Var1, c.Var2, c.Var3 }) 
        .Where(g => g.Count() > 1) 
        .Select(g => g.Key.Var3) 
        .ToList(); 

Это дает 229 результатов (все записи). Запрос, который я хотел бы построить в Linq является:

SELECT Var3 
FROM myTable 
GROUP BY Var1, Var2, Var3 
HAVING COUNT(*) > 1 

Каким-то образом, запрос дает мне 27 результатов, но выражение Linq дает мне 229 (все). Когда я заменить Где/выберите часть выражения Linq к следующему, я получаю список с подсчетами, которые являются 2 или выше:

.Select(g => new { Item = g.Key, Count = g.Count() }) 

Но я не хочу список с пунктами (и подсчетами) и имеющим чтобы пройти этот список, я хотел бы, чтобы часть HAVING работала в выражении Linq ...

Редактировать 2: Если вы посмотрите на LINQ Group By Multiple fields -Syntax help, это также работает для меня. Тем не менее, я получу список объектов с Var1, Var2, Var3 и Count. Из этого списка я хочу только Var3 объектов с графом выше 1.

Любой, кто может указать мне в правильном направлении?

Редактировать 1: Как я уже говорил в своем вступительном слове, вопрос Linq with group by having count не отвечает на мою проблему. Если я использую этот код, у меня все еще есть набор из 229 результатов вместо 27, которые на самом деле «дублируются» (что означает, что после группы, имеющей счет более 1).

Редактировать 3: В данный момент я использую следующее. Я нужны два заявления, и я думаю, что это странно, но, как было сказано выше, это, кажется, единственный способ, чтобы выбрать только те записи, имеющие счета> 1.

var querygroup = session.Query<SomeClass>() 
         .GroupBy(e => new { e.Var1, e.Var2, e.Var3 }) 
         .Select(s => new { s.Key.Var1, s.Key.Var2, s.Key.Var3, Count = s.Count() }) 
         .ToList(); 

var duplicates = querygroup.Where(g => g.Count > 1) 
          .Select(g => new SomeClass() { Var1 = g.Var1, Var2 = g.Var2, Var3 = g.Var3}) 
          .ToList(); 

Обратите внимание, что вместо того, чтобы выбрать только var3, я решили выбрать значения Var1 и Var2 и сохранить их в SomeClass(). Это просто дополнение, выбор всего не помогает с созданием 1-го утверждения, чтобы получить этот выбор.

Редактировать 4: Я могу, конечно, принять .Where.. часть в переменной duplicates и добавить ее в оператор querygroup, тем самым делая все одно утверждение. Успех? Кажется, слишком много, но по крайней мере это работает.

Если кто-то может узнать, почему мне нужно 2 заявления, пожалуйста, подробно :)

+0

Возможный дубликат [Linq с группой по количеству] (http://stackoverflow.com/questions/2078736/linq-with-group-by-having-count) –

+0

Добавлен «редактирование» на мой вопрос , Как я сказал в своем вступительном слове, я попробовал, но это не дает мне «правильный» результат. – Tjab

+1

Чтобы определить, есть ли проблема с переведенным SQL-запросом, попробуйте 'var testA = session.Query () .GroupBy (c => new {c.Var1, c.Var2, c.Var3}) ToList (); var test = testA.Where (g => g.Count()> 1). Выберите (g => g.Key.Var3) .ToList(); 'и посмотрите, что вы получите. –

ответ

0

Таким образом, ответ на мой вопрос:

var duplicates = session.Query<SomeClass>() 
         .GroupBy(e => new { e.Var1, e.Var2, e.Var3 }) 
         .Select(s => new { s.Key.Var1, s.Key.Var2, s.Key.Var3, Count = s.Count() }) 
         .ToList() 
         .Where(g => g.Count > 1) 
         .Select(g => new SomeClass() { Var1 = g.Var1, Var2 = g.Var2, Var3 = g.Var3}) 
         .ToList(); 

Кажется немного излишним, я чувствую, что это может быть меньше, так что если кто-то любит комментировать. ..

0

Вы можете попробовать это в Linqpad. Я изменил таблицу и столбец имя вашего запроса в соответствии с моей собственной БД:

Levels 
.GroupBy(c => new { c.CourseGuid, c.ModuleName }) 
.Where(g => g.Count() > 10) 
.Select(g => g.Key.CourseGuid) 

Это был SQL запросов было произведено:

-- Region Parameters 
DECLARE @p0 Int = 10 
-- EndRegion 
SELECT [t1].[CourseGuid] 
FROM (
    SELECT COUNT(*) AS [value], [t0].[CourseGuid] 
    FROM [xrt].[Levels] AS [t0] 
    GROUP BY [t0].[CourseGuid], [t0].[ModuleName] 
    ) AS [t1] 
WHERE [t1].[value] > @p0 

Не один с HAVING COUNT, но с WHERE вместо этого, и функционально идентичны. Воспроизведение с параметрами @ p0 показывает, что выход фильтруется правильно.

Я рекомендую вам попробовать с Linqpad, чтобы узнать, что ваш запрос делает против ваших данных.

+0

Но это то же самое, что 'HAVING' внутри подзапроса. –

+0

@ ИванСтоев, вы правы. Я исправил свой ответ. –

1

Попробуйте

var test = session.Query<SomeClass>() 
        .GroupBy(c => new { c.Var1, c.Var2, c.Var3 }) 
        .Select(d=> new { var1 = d.Key.var1,var2 = d.Key.var2,var3=d.Key.var3,records = d.ToList()}) 
        .Where(e => e.records.Count() > 1) 
        .Select(g => g.Var3) 
        .ToList(); 
+0

У меня были большие надежды, потому что кажется правильным, но все же слишком много записей (очень уверен, что он пропускает часть счета и выбирает все записи). Ваш пример имеет тот же результат, что и «SELECT Var3 FROM table GROUP BY Var1, Var2, Var3 HAVING COUNT (*)> 1', когда я удаляю часть' HAVING'. – Tjab

+0

Еще лучше, в вашем примере, если я изменю выбранную часть на '.Select (g => g.records.Count())', я получаю список из 229 (всех) записей, что-то вроде '1,1, 1,1,1,1,4,1,1,1,1,1,1,1,1,5,1,1,1,1,1' и т. Д. (27 раз НЕ 1). Я очень смущен этим, так как я хотел бы выбрать только записи NOT 1 .... – Tjab

+1

@Tjab Я обновил answer..give, который также попытался .... Я материализовал записи, выполнив ToList .. . Я чувствую, что есть какая-то проблема, возникающая из-за дефферентного исполнения. Это больше похоже на догадку, дайте ей попробовать. Попытайтесь, чтобы ваш вопрос, о котором идет речь, должен работать. – Viru