2016-10-11 4 views
-1

у меня есть история таблица заказанных товаровПолучить уникальный ряд со многими условиями

+----+------------+--------+ 
| id | IdProduct | status | 
+----+------------+--------+ 
| 1 | 100  | 1  | 
| 2 | 100  | 2  | 
| 3 | 100  | 3  | 
| |   |  | 
| 4 | 200  | 1  | 
| 5 | 200  | 2  | 
| |   |  | 
| 6 | 300  | 1  | 
| 7 | 300  | 2  | 
+----+------------+--------+ 

Я хочу, чтобы получить только те продукты, которые имеют статус 2 но не 3

+----+------------+ 
| id | IdProduct | 
+----+------------+ 
| 5 | 200  | 
| |   | 
| 7 | 300  | 
+----+------------+ 

Как я могу достичь это с использованием запроса Linq

+0

Почему бы вам не просто использовать SQL? Как и в, использовать SQL и делать это через PetaPoco? – code4life

ответ

2

с помощью LINQ к SQL вы можете do:

var result = history.GroupBy(item => item.IdProduct) 
        .Where(grp => grp.Any(item => item.Status == 2) && 
           !grp.Any(item => item.Status == 3)) 
        .Select(grp => new { 
         IdProduct = grp.Key, 
         Id = grp.Max(item => item.Id) 
        }); 

Или:

var result = history.GroupBy(item => item.IdProduct) 
        .Where(grp => grp.Any(item => item.Status == 2) && 
           !grp.Any(item => item.Status == 3)) 
        .Select(grp => grp.Where(item => ite.Status == 2).FirstOrDefault()); 

В вашем случае, как они должны вернуться в тот же потому, что Макс (идентификатор) correleted с результатом вы хотели

Если вы знаете, каждый статус существует только один раз, то вы можете попробовать следующее. Идея заключается в том, что статус 3 пунктов равен -1, 2 равен 1, а остальные 0. Только группы, которые имеют статус 2, но не 3 будет иметь результат 1

var result = history.Select(item => new { Item = item, Valid = item.Status == 2 ? 1 : item.Status == 3 ? -1 : 0 }) 
        .GroupBy(item => item.Item.IdProduct) 
        .Where(grp => grp.Sum(item => item.Valid) == 1) 
        .Select(item => item.Item); 
2

Я не читал последнюю строку, о которой идет речь Как достичь этого, используя запрос Linq может быть, что причина downvote ..

Будет держать этот ответ, если кто-то ищет, чтобы решить эту проблему в SQL


Вот один из способов использования Group by и Having пункт

SELECT * 
FROM yourtable 
WHERE IdProduct IN (SELECT IdProduct 
        FROM Yourtable 
        GROUP BY IdProduct 
        HAVING Count(CASE WHEN status = 3 THEN 1 END) = 0 
          AND Count(CASE WHEN status = 2 THEN 1 END) > 0) 
     AND Status = 2 

Count(CASE WHEN status = 3 THEN 1 END) = 0

Это условие, чтобы убедиться, что status = 3 не существует какой-либо строке для каждого ID

Count(CASE WHEN status = 2 THEN 1 END) > 0

Это условие, чтобы убедиться, alteast один ряд с status = 2 для каждого ID

+1

Downvoter осмеливается прокомментировать? –

+0

Я честно не понимаю, почему люди хотят использовать Linq - это как если бы они не верили, что «самый простой - лучший», бритва la Occam's. – code4life

1
Declare @YourTable table (id int,IdProduct int,status int) 
Insert Into @YourTable values 
(1 , 100 , 1), 
(2 , 100 , 2), 
(3 , 100 , 3), 
(4 , 200 , 1), 
(5 , 200 , 2), 
(6 , 300 , 1), 
(7 , 300 , 2) 


Select Id,IdProduct 
    From (
     Select Id 
       ,IdProduct 
       ,MaxStatus = max(Status) over (Partition By IdProduct) 
      From @YourTable 
      Where Status in (2,3) 
     ) A 
    Where MaxStatus = 2 

Возвращения

Id IdProduct 
5 200 
7 300 
+0

Добавить эту запись, это не сработает '(5, 200, 4)';) –

+0

@Prdp Очень верно .. при условии, что есть статус 4+ –

+0

Независимо от +1 для использования агрегированной функции окна Мне нравится эта функция –

Смежные вопросы