[.net] LINQ to SQL 왼쪽 외부 조인

이 쿼리는 LEFT OUTER조인 과 동일 합니까?

//assuming that I have a parameter named 'invoiceId' of type int
from c in SupportCases
let invoice = c.Invoices.FirstOrDefault(i=> i.Id == invoiceId)
where (invoiceId == 0 || invoice != null)
select new
{
      Id = c.Id
      , InvoiceId = invoice == null ? 0 : invoice.Id
}



답변

왼쪽-외부 조인의 각 “왼쪽”행은 0-n “오른쪽”행 (두 번째 테이블)과 일치하므로 0-1 만 일치합니다. 왼쪽 외부 조인을 수행하려면, 당신은 필요 SelectMany하고 DefaultIfEmpty, 예를 들면 :

var query = from c in db.Customers
            join o in db.Orders
               on c.CustomerID equals o.CustomerID into sr
            from x in sr.DefaultIfEmpty()
            select new {
               CustomerID = c.CustomerID, ContactName = c.ContactName,
               OrderID = x == null ? -1 : x.OrderID };   

( 또는 확장 방법을 통해 )


답변

into 문은 필요하지 않습니다.

var query =
    from customer in dc.Customers
    from order in dc.Orders
         .Where(o => customer.CustomerId == o.CustomerId)
         .DefaultIfEmpty()
    select new { Customer = customer, Order = order }
    //Order will be null if the left join is null

그리고 예, 위의 쿼리는 실제로 LEFT OUTER 조인을 만듭니다.

여러 왼쪽 조인을 처리하는 비슷한 질문에 연결 :
Linq to Sql : 여러 왼쪽 외부 조인


답변

Public Sub LinqToSqlJoin07()
Dim q = From e In db.Employees _
        Group Join o In db.Orders On e Equals o.Employee Into ords = Group _
        From o In ords.DefaultIfEmpty _
        Select New With {e.FirstName, e.LastName, .Order = o}

ObjectDumper.Write(q) End Sub

http://msdn.microsoft.com/en-us/vbasic/bb737929.aspx 확인


답변

1 솔루션을 찾았습니다. 이런 종류의 SQL (왼쪽 조인)을 Linq 엔터티로 변환하려면 …

SQL :

SELECT * FROM [JOBBOOKING] AS [t0]
LEFT OUTER JOIN [REFTABLE] AS [t1] ON ([t0].[trxtype] = [t1].[code])
                                  AND ([t1]. [reftype] = "TRX")

LINQ :

from job in JOBBOOKINGs
join r in (from r1 in REFTABLEs where r1.Reftype=="TRX" select r1)
          on job.Trxtype equals r.Code into join1
from j in join1.DefaultIfEmpty()
select new
{
   //cols...
}


답변

한 가지 더 추가하고 싶습니다. LINQ to SQL에서 DB가 올바르게 빌드되고 테이블이 외래 키 제약 조건을 통해 관련된 경우에는 조인을 전혀 수행 할 필요가 없습니다.

LINQPad를 사용하여 다음 LINQ 쿼리를 만들었습니다.

//Querying from both the CustomerInfo table and OrderInfo table
from cust in CustomerInfo
where cust.CustomerID == 123456
select new {cust, cust.OrderInfo}

아래의 (약간 잘린) 쿼리로 번역 된 것

 -- Region Parameters
 DECLARE @p0 Int = 123456
-- EndRegion
SELECT [t0].[CustomerID], [t0].[AlternateCustomerID],  [t1].[OrderID], [t1].[OnlineOrderID], (
    SELECT COUNT(*)
    FROM [OrderInfo] AS [t2]
    WHERE [t2].[CustomerID] = [t0].[CustomerID]
    ) AS [value]
FROM [CustomerInfo] AS [t0]
LEFT OUTER JOIN [OrderInfo] AS [t1] ON [t1].[CustomerID] = [t0].[CustomerID]
WHERE [t0].[CustomerID] = @p0
ORDER BY [t0].[CustomerID], [t1].[OrderID]

LEFT OUTER JOIN위를 주목하십시오 .


답변

성능을 관리하십시오.

적어도 EF Core 에서는 여기에 주어진 다른 답변이 다른 성능을 초래할 수 있다는 것을 경험했습니다 . OP가 Linq to SQL에 대해 물었다는 것을 알고 있지만 EF Core에서도 동일한 질문이 발생하는 것으로 보입니다.

내가 처리해야 할 특정 사례에서 Marc Gravell의 (구문 적으로 더 좋은) 제안은 Mike U가 묘사 한 것과 유사하게 크로스 적용 내부에서 왼쪽 조인을 초래 하여이 특정 쿼리의 추정 ​​비용이 2라는 결과를 얻었습니다. 교차 조인이없는 쿼리에 비해 시간이 많이 걸립니다 . 서버 실행 시간 은 3 배로 다릅니다 . [1]

Marc Gravell의 솔루션으로 교차 조인이없는 쿼리가 발생했습니다.

컨텍스트 : 기본적으로 두 테이블에서 두 개의 왼쪽 조인을 수행해야했는데 각각의 테이블에는 다시 다른 테이블에 대한 조인이 필요했습니다. 또한 왼쪽 조인을 적용 해야하는 테이블에 다른 위치 조건을 지정해야했습니다. 또한 기본 테이블에 두 개의 내부 조인이있었습니다.

예상 운영자 비용 :

  • 크로스 적용 : 0.2534
  • 십자가없이 적용 : 0.0991.

서버 실행 시간 (ms) (쿼리가 10 번 실행되었으며 SET STATISTICS TIME ON을 사용하여 측정 된 쿼리) :

  • 크로스 적용 : 5, 6, 6, 6, 6, 6, 6, 6, 6, 6
  • 크로스 적용없이 : 2, 2, 2, 2, 2, 2, 2, 2, 2, 2

(처음 실행은 두 쿼리 모두에 대해 느려졌습니다. 캐시 된 것으로 보입니다.)

테이블 크기 :

  • 메인 테이블 : 87 행,
  • 왼쪽 조인의 첫 번째 테이블 : 179 행;
  • 왼쪽 조인의 두 번째 테이블 : 7 행

EF 코어 버전 : 2.2.1.

SQL Server 버전 : MS SQL Server 2017-14 … (Windows 10).

모든 관련 테이블에는 기본 키에 대한 인덱스 만있었습니다.

내 결론 : 생성 된 SQL은 실제로 다를 수 있으므로 항상 보는 것이 좋습니다.


[1] 흥미롭게도 MS SQL Server Management Studio에서 ‘클라이언트 통계’를 설정할 때 반대 경향을 볼 수있었습니다. 즉, 교차 적용이없는 마지막 솔루션 실행에는 1 초 이상이 걸렸습니다. 내 설정에 문제가 있다고 생각합니다.


답변