如何使用LINQ实现SELECT WHERE NOT EXIST?

64
我必须列出所有要分配给“员工”的“班次”数据,但是如果班次数据已经存在于员工的数据中,则不能包括在内。请看下面的图片示例。

No filtering yet

这个查询可以解决这个问题。我在这里找到了它:
Scott's Blog
select * from shift where not exists 
(select 1 from employeeshift where shift.shiftid = employeeshift.shiftid
and employeeshift.empid = 57);  

让我们来看一下结果:

Filtered

现在我的问题是,我该如何在linQ中实现这个呢?我正在使用Entity Framework。
希望有人能帮忙。非常感谢!!!


1
如果右记录不存在,则您可以简单地执行连接...左记录不应包括在内。 - user57508
@AndreasNiedermair 你能提供一些例子吗?我已经尝试了很多连接但都不对。 - fiberOptics
1
你可以参考其他 Stack Overflow 主题:https://dev59.com/kXNA5IYBdhLWcg3wmfEa 来使用 Linq 中的 WHERE NOT IN 语句。 - korzeniow
可能是LINQ - Where not exists的重复问题。 - user57508
6个回答

116
from s in context.shift
where !context.employeeshift.Any(es=>(es.shiftid==s.shiftid)&&(es.empid==57))
select s;

"&&es.empid=57" 必须在 "(es.shiftid==s.shiftid)" 内部。它可以工作,但是它不能返回完整的数据,一些数据会丢失。 - fiberOptics

32

输出的SQL可能会不同,但结果应该是相同的:

var shifts = Shifts.Where(s => !EmployeeShifts.Where(es => es.ShiftID == s.ShiftID).Any());

5
判断是否有结果时应始终使用 Any() 而非 Count() - Nuffin
5
你应该使用 !.Any() 而不是 count。如果没有元素,性能将相同,但在所有有多个元素的情况下,any 会更快,因为它在找到第一个元素后停止迭代。 - Rune FS
你失去了 empid = 57 的条件? - Arsen Mkrtchyan

3

首先,我建议稍微修改一下你的SQL查询:


 select * from shift 
 where shift.shiftid not in (select employeeshift.shiftid from employeeshift 
                             where employeeshift.empid = 57);

这个查询提供了相同的功能。如果你想用LINQ得到相同的结果,可以尝试以下代码:

//Variable dc has DataContext type here
//Here we get list of ShiftIDs from employeeshift table
List<int> empShiftIds = dc.employeeshift.Where(p => p.EmpID = 57).Select(s => s.ShiftID).ToList();

//Here we get the list of our shifts
List<shift> shifts = dc.shift.Where(p => !empShiftIds.Contains(p.ShiftId)).ToList();

1
你的 SQL 查询完美无缺。但在 LINQ 中,我只需要一个查询就可以了。谢谢! - fiberOptics

0
从我在这里看到的情况来看,大多数解决方案都基于IN或NOT IN子句。我认为左连接和WHERE ID IS NULL类型的解决方案更好。这是我正在使用的方法。
var linqQuery = 
from shift in context.Shift.Where(x=> x.IfYouHaveMoreConditions == true)
from employeeShift in context.EmployeeShift.Where(x=> shift.ShiftId == x.ShiftId ) /* this will become your left join condition */
where employeeShift.ShiftId == null /*this will create a compiler warning, because the ID cannot be null, but will still work and compile and is necessary*/
select shift;

然后,这将导致以下SQL语句:
SELECT shift.* FROM shift
LEFT OUTER JOIN emlpoyeeshift ON shift.shiftid = employeeshift.shiftid
WHERE emlployeeshift.shiftid IS NULL

然后你叔叔就是鲍勃


-1

怎么样..

var result = (from s in context.Shift join es in employeeshift on s.shiftid equals es.shiftid where es.empid == 57 select s)

编辑:这将为您提供存在关联员工班次的班次(因为有连接)。对于“不存在”,我会按照@ArsenMkrt或@hyp的建议进行操作


是的,我意识到我实际上没有回答正确的问题! - Matt Roberts
是的,由于结果应该是结果集,你得到了布尔值。 - Arsen Mkrtchyan

-2
        Dim result2 = From s In mySession.Query(Of CSucursal)()
                      Where (From c In mySession.Query(Of CCiudad)()
                             From cs In mySession.Query(Of CCiudadSucursal)()
                             Where cs.id_ciudad Is c
                             Where cs.id_sucursal Is s
                             Where c.id = IdCiudad
                             Where s.accion <> "E" AndAlso s.accion <> Nothing
                             Where cs.accion <> "E" AndAlso cs.accion <> Nothing
                             Select c.descripcion).Single() Is Nothing
                      Where s.accion <> "E" AndAlso s.accion <> Nothing
                      Select s.id, s.Descripcion

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接