2009-08-12 3 views
22

AND이 아닌 조건이 OR 인 여러 조건에서 왼쪽 조인을 수행해야합니다. 후자의 샘플을 많이 찾았지만 내 시나리오에 대한 올바른 대답을 얻으려고 애 쓰고 있습니다.Linq - 다중 (OR) 조건에 왼쪽으로 결합

from a in tablea 
join b in tableb on new { a.col1, a.col2 } equals new { b.col1, b.col2 } 
group a by a into g 
select new() { col1 = a.col1, col2 = a.col2, count = g.Count() } 

은 모든 조건이 일치해야하는 조인에 좋습니다. 조인을 on a.col1 = b.col1 OR a.col2 = b.col2과 일치시켜야합니다.

나는 그것이 쉬워야한다라는 것을 알고있다. 그러나 나는 이것 위에서 비어있게되었다!

편집 :

좀 더 많은 정보를 제공하기 위해, 쿼리의 목적은 'A' 'B'에 일치하는 레코드의 카운트 플러스에서 모든 필드를 포함하는 투사를 얻는 것입니다. 위의 샘플을 수정하여 내가 무엇을하고 있는지 보여줍니다. Jon Skeet의 접근법을 사용하여 위와 같이 실행하면 b의 관련 레코드 수가 아닌 모든 레코드의 수가 증가합니다.

from a in tablea 
from b in tableb 
.Where(b => (a.col1 == b.col1 || a.col2 == b.col2)) 
.DefaultIfEmpty() 
select new { col1 = a.col1, col2 = a.col2 } 

내가

from a in tablea 
from b in tableb 
.Where(b => (a.col1 == b.col1 || a.col2 == b.col2)) 
.DefaultIfEmpty() 
group a by a.col1 into g 
select new { col1 = g.Key, count = g.Count() } 

이하 나는 레코드의 수를 얻고으로 그룹을 추가 할 그것을 수정하는 경우가에서 반환 -하지 :

기본 왼쪽은 좋은 작품에 참여 일치하는 레코드의 수 b.

편집

: 나는 존에 대한 답을주지

- 나는 나의 카운트 문제를 해결했습니다 - 내가 개수 (g.Count(x => x != null))를 필터링 할 람다를 사용할 수 있습니다 실현하지 않았다. 게다가 위에서 b와 같이 a를 b로 묶어야합니다. 이것은 정확한 결과를 제공하지만 SQL은 상관 관계가있는 하위 쿼리를 추가 할 때 손으로 쓰는 것만 큼 효율적이지 않습니다. 다음 SQL을 시뮬레이트하기 위해 더 나은 방법을 조언 할 수 있다면 감사하겠습니다.

select a.col1, count(b.col1) 
from tablea a 
left join tableb b 
on a.col1 = b.col1 
or a.col2 = b.col2 
group by a.col1 
+0

그룹화하지 않고 * 내 쿼리 *를 시도하고 그 결과가 원하는지 확인하십시오. 그렇다면 그룹화가 실패한 이유를 찾으십시오. 아마도'new {a.col1, a.col2} '에 의해 그룹화 할 것인가? –

+0

기본 왼쪽 조인 선택으로 잘 작동합니다. 그룹핑에서 카운트를 얻는 것이 이것이 기본 동등 조인이라면 기대했던대로 작동하지 않습니다. 위의 추가 정보에 유의하십시오. –

답변

32

LINQ는 equijoins 만 직접 지원합니다. 당신이 가입의 다른 어떤 종류의 일을하려는 경우, 당신은 기본적으로 필요 십자가를 조인하고 where :

from a in tablea 
from b in tableb 
where a.col1 == b.col1 || a.col2 == b.col2 
select ... 

그것은 확인 아마 가치가 무엇 생성 된 SQL의 모습을 어떤 쿼리 계획이 같다. 그것을하는 더 효율적인 방법이 있을지도 모르지만, 이것은 가장 단순한 접근 일 것입니다.

+0

나는이 접근법으로 시작했다. 나는 실제로 a에서 모든 레코드를 얻고 b와 일치하는 레코드의 수를 얻기 위해 적절한 쿼리로 그룹화하고있다. 게시물을 수정하여 명확하게합니다. –

20

쿼리 공급자에 따라, 당신은 절에서 2 장을 사용하도록 선택할 수 있습니다 :

from a in tablea 
from b in tableb 
where a.col1 == b.col1 || a.col2 == b.col2 

어떤을, 당신은 DB에서 실행하면, 그냥 효율적입니다. 인 메모리 (Linq to Objects)를 실행하면 모든 가능한 조합이 나열되어 비효율적 일 수 있습니다.

Arg, Skeeted ;-).

더 효율적인 Linq to Objects 대안이 가능합니다. join 연산자는 각 소스를 한 번만 열거 한 다음 해시 조인을 수행하므로 or 절을 두 개의 별도 조인으로 분리 한 다음 해당 조 합을 수행 할 수 있습니다.LINQ의 노동 조합은 중복없이 단지 연결, 그래서 다음과 같이 그 보일 것이다

(from a in tablea 
join b in tableb on a.Col1 equals b.Col1 
select new {a, b}) 
.Concat(
from a in tablea 
join b in tableb on a.Col2 equals b.Col2 
select new {a, b} 
).Distinct() 

이 방법을 작동하고, 그것은 단지 하나의 쿼리, 그러나 그것은 의미에서 다소 비 분명 그의 성능 특성 코드는 linq 작동 방식에 대한 이해에 따라 다릅니다. 개인적으로 여러 개의 일치 항목이있는 해시 조인을 수행하려는 경우 더 확실한 도구는 ToLookup입니다. 로 보일 수 있습니다 그것을 사용하는 대안은 다음과 같습니다

var bBy1 = tableb.ToLookup(b=>b.Col1); 
var bBy2 = tableb.ToLookup(b=>b.Col2); 
var q3 = 
    from a in tablea 
    from b in bBy1[a.Col1].Concat(bBy2[a.Col2]).Distinct() 
    ... 

이 솔루션은 실제로 짧은, 그것이 작동하는 이유는 더 분명하다, 그래서 내가 선호하려는 하나입니다. 위의 두 가지 시나리오와 같이 || 연산자를 두 개의 개별 쿼리로 분리하면 수동으로 결과를 이중 계산하지 않아야합니다 (예 : Distinct 사용).

+0

개체에 Linq를 사용하고 있습니다. 대체 솔루션이 있습니까? – Kev

+0

예, 편집을 참조하십시오! –

+0

가입 해 주셔서 감사합니다. : http://chat.stackoverflow.com/rooms/info/17239/kryptonite – Kev