获得具有许多条件的独特行

时间:2016-10-11 16:53:34

标签: c# linq

我有一个订购产品的历史表

+----+------------+--------+
| 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请求实现此目的

3 个答案:

答案 0 :(得分:2)

我没有看到问题的最后一行如何使用Linq请求实现此目的可能是downvote的原因..

如果有人希望在SQL

中解决问题,请保留此答案

以下是使用Group byHaving子句

的一种方法
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

这个条件是为每个status = 2

确保更改一行ID

答案 1 :(得分:2)

使用linq to sql可以:

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());

在你的情况下,这两个都应该返回相同,因为max(id)与你想要的结果相关

如果您知道每个状态只存在一次,那么您可以尝试以下操作。想法是状态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 :(得分: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