LINQ를 사용하여 "not in"쿼리를 어떻게 수행 하시겠습니까?
두 컬렉션 Email
모두에 속성이있는 두 개의 컬렉션이 있습니다 . 첫 번째 목록에서 Email
두 번째 목록에없는 항목 목록을 가져와야 합니다. SQL에서는 "not in"만 사용하지만 LINQ에서 이에 상응하는 것을 알지 못합니다. 어떻게됩니까?
지금까지 나는 ...
var matches = from item1 in list1
join item2 in list2 on item1.Email equals item2.Email
select new { Email = list1.Email };
그러나 차이가 필요하고 참여가 실패하기 때문에 참여할 수 없습니다. 포함 또는 존재하는 것으로 생각하는 방법이 필요합니다. 나는 아직 그 일을하는 예를 찾지 못했습니다.
이것이 도움이 될지 모르겠지만 ..
NorthwindDataContext dc = new NorthwindDataContext();
dc.Log = Console.Out;
var query =
from c in dc.Customers
where !(from o in dc.Orders
select o.CustomerID)
.Contains(c.CustomerID)
select c;
foreach (var c in query) Console.WriteLine( c );
에서 SQL에 LINQ에서 NOT IN 절 에 의해 마르코 루소
제외 연산자를 원합니다.
var answer = list1.Except(list2);
여기에 더 나은 설명 : http://blogs.msdn.com/charlie/archive/2008/07/12/the-linq-set-operators.aspx
참고 : 이 기술은 복잡한 형식에 Except 메서드를 사용하려면 IEqualityComparer 를 구현해야하므로 기본 형식에만 가장 적합 합니다.
두 번째 목록에 이메일이없는 첫 번째 목록의 항목.
from item1 in List1
where !(list2.Any(item2 => item2.Email == item1.Email))
select item1;
메모리 내 객체 그룹으로 시작하여 데이터베이스에 대해 쿼리하는 사람들에게 이것이 최선의 방법이라는 것을 알았습니다.
var itemIds = inMemoryList.Select(x => x.Id).ToArray();
var otherObjects = context.ItemList.Where(x => !itemIds.Contains(x.Id));
이것은 WHERE ... IN (...)
SQL에서 멋진 절을 생성합니다 .
찾을 수없는 위치에 Where 및 Any 조합을 사용할 수 있습니다.
var NotInRecord =list1.Where(p => !list2.Any(p2 => p2.Email == p.Email));
list1과 list2의 두 가지 다른 목록으로 두 컬렉션을 모두 가져올 수 있습니다.
그런 다음 쓰기
list1.RemoveAll(Item => list2.Contains(Item));
작동합니다.
ADO.NET Entity Framework를 사용하는 경우 EchoStorm의 솔루션도 완벽하게 작동합니다. 그러나 머리를 감싸는 데 몇 분이 걸렸습니다. 데이터베이스 컨텍스트 dc가 있고 테이블 y에 링크되지 않은 테이블 x에서 행을 찾으려고 가정하면 전체 답변은 다음과 같습니다.
var linked =
from x in dc.X
from y in dc.Y
where x.MyProperty == y.MyProperty
select x;
var notLinked =
dc.X.Except(linked);
Andy의 의견에 따라 LINQ 쿼리에서 from을 두 개 가질 수 있습니다. 다음은 목록을 사용하는 완전한 작업 예입니다. 각 클래스 인 Foo and Bar에는 ID가 있습니다. Foo에는 Foo.BarId를 통해 Bar에 대한 "외부 키"참조가 있습니다. 프로그램은 해당 바에 연결되지 않은 모든 Foo를 선택합니다.
class Program
{
static void Main(string[] args)
{
// Creates some foos
List<Foo> fooList = new List<Foo>();
fooList.Add(new Foo { Id = 1, BarId = 11 });
fooList.Add(new Foo { Id = 2, BarId = 12 });
fooList.Add(new Foo { Id = 3, BarId = 13 });
fooList.Add(new Foo { Id = 4, BarId = 14 });
fooList.Add(new Foo { Id = 5, BarId = -1 });
fooList.Add(new Foo { Id = 6, BarId = -1 });
fooList.Add(new Foo { Id = 7, BarId = -1 });
// Create some bars
List<Bar> barList = new List<Bar>();
barList.Add(new Bar { Id = 11 });
barList.Add(new Bar { Id = 12 });
barList.Add(new Bar { Id = 13 });
barList.Add(new Bar { Id = 14 });
barList.Add(new Bar { Id = 15 });
barList.Add(new Bar { Id = 16 });
barList.Add(new Bar { Id = 17 });
var linked = from foo in fooList
from bar in barList
where foo.BarId == bar.Id
select foo;
var notLinked = fooList.Except(linked);
foreach (Foo item in notLinked)
{
Console.WriteLine(
String.Format(
"Foo.Id: {0} | Bar.Id: {1}",
item.Id, item.BarId));
}
Console.WriteLine("Any key to continue...");
Console.ReadKey();
}
}
class Foo
{
public int Id { get; set; }
public int BarId { get; set; }
}
class Bar
{
public int Id { get; set; }
}
var secondEmails = (from item in list2
select new { Email = item.Email }
).ToList();
var matches = from item in list1
where !secondEmails.Contains(item.Email)
select new {Email = item.Email};
Except
답변의 일부 이지만 전체 답변이 아닙니다. 기본적으로 Except
(여러 LINQ 연산자와 같이) 참조 유형에 대한 참조 비교를 수행합니다. 객체의 값을 기준으로 비교하려면
IEquatable<T>
귀하의 유형으로 구현 하거나- 재정의
Equals
및GetHashCode
유형 또는 - 타입을 구현하는 타입의 인스턴스를 전달
IEqualityComparer<T>
하십시오.
하나도 사용할 수 있습니다 All()
var notInList = list1.Where(p => list2.All(p2 => p2.Email != p.Email));
단순화를 위해 int 목록을 사용하는 예.
List<int> list1 = new List<int>();
// fill data
List<int> list2 = new List<int>();
// fill data
var results = from i in list1
where !list2.Contains(i)
select i;
foreach (var result in results)
Console.WriteLine(result.ToString());
IN
C #에서 SQL 유사 연산자 를 사용하려는 사람은 이 패키지를 다운로드하십시오.
Mshwf.NiceLinq
그것 In
과 NotIn
방법 :
var result = list1.In(x => x.Email, list2.Select(z => z.Email));
이런 식으로도 사용할 수 있습니다
var result = list1.In(x => x.Email, "a@b.com", "b@c.com", "c@d.com");
감사합니다, 브렛 당신의 제안도 나에게 도움이되었습니다. 객체 목록이 있었고 다른 객체 목록을 사용하여 필터링하려고했습니다. 다시 감사합니다 ....
누구든지 필요한 경우 내 코드 샘플을 살펴보십시오.
'First, get all the items present in the local branch database
Dim _AllItems As List(Of LocalItem) = getAllItemsAtBranch(BranchId, RecordState.All)
'Then get the Item Mappings Present for the branch
Dim _adpt As New gItem_BranchesTableAdapter
Dim dt As New ds_CA_HO.gItem_BranchesDataTable
_adpt.FillBranchMappings(dt, BranchId)
Dim _MappedItems As List(Of LocalItem) = (From _item As LocalItem In _AllItems Join _
dr As ds_CA_HO.gItem_BranchesRow In dt _
On _item.Id Equals dr.numItemID _
Select _item).ToList
_AllItems = _AllItems.Except(_MappedItems.AsEnumerable).ToList
Return _AllItems
나는 이것을 LINQ to Entities로 테스트하지 않았다 .
NorthwindDataContext dc = new NorthwindDataContext();
dc.Log = Console.Out;
var query =
from c in dc.Customers
where !dc.Orders.Any(o => o.CustomerID == c.CustomerID)
select c;
또는
NorthwindDataContext dc = new NorthwindDataContext();
dc.Log = Console.Out;
var query =
from c in dc.Customers
where dc.Orders.All(o => o.CustomerID != c.CustomerID)
select c;
foreach (var c in query)
Console.WriteLine( c );
그룹이 비어있는 경우 첫 번째 목록에서만 항목을 선택하여 외부 조인을 수행 할 수 없습니까? 다음과 같은 것 :
Dim result = (From a In list1
Group Join b In list2
On a.Value Equals b.Value
Into grp = Group
Where Not grp.Any
Select a)
이것이 Entity 프레임 워크에서 효율적인 방식으로 작동하는지 확실하지 않습니다.
또는 다음과 같이 할 수 있습니다 :
var result = list1.Where(p => list2.All(x => x.Id != p.Id));
참고 URL : https://stackoverflow.com/questions/183791/how-would-you-do-a-not-in-query-with-linq
'IT' 카테고리의 다른 글
Eclipse에서 작업 공간을 삭제하는 방법? (0) | 2020.03.19 |
---|---|
MySQL 데이터베이스에 연결할 때 SSL 연결에 대한 경고 (0) | 2020.03.19 |
Visual Studio Code에서 구문 강조를위한 언어를 수동으로 설정하는 방법 (0) | 2020.03.19 |
반응 형 레이아웃에서 요소를 숨기시겠습니까? (0) | 2020.03.19 |
오류 2006 (HY000) : MySQL 서버가 사라졌습니다 (0) | 2020.03.19 |