2010-01-22 3 views
0

이 SQL을 LINQ로 변환하고 싶습니다. (그 3 열을 기준 테이블 생산없는 입력에서 행을 선택 shouldl 두 테이블 컬럼이 NULL이 포함 된 경우,이를 고려해야 동일한 값을 구비한다.) 모든이 SQL 쿼리를 Linq (Not Exists + sub query)로 변환하십시오.

SELECT i.* FROM INPUT AS i 
WHERE NOT EXISTS 
(SELECT p.Agent FROM Production AS p 
WHERE ISNULL(i.CustID,'') <> ISNULL(p.CustID,'') 
AND ISNULL(i.CustName,'') <> ISNULL(p.CustName,'') 
AND ISNULL(i.household,'') <> ISNULL(p.Household,'')) 

답변

4

퍼스트 -이 좋은 SQL 쿼리가 아닙니다. 모든 열은 sargable이 아닌 함수로 싸여 있습니다. 즉, 엔진이 해당 열의 인덱스를 이용할 수 없다는 것을 의미합니다. 반 괜찮은 SQL 쿼리로이를 다시 작성하여

하자의 시작 :

지금이, LEFT JOIN/IS NULL 어느 효율성을 위해 좋은 것이 아니라 우리가이기 때문에 우리는 여기에 많은 선택의 여지가 없어 미루어
SELECT i.* 
FROM Input i 
LEFT JOIN Production p 
    ON (p.CustID = i.CustID OR (p.CustID IS NULL AND i.CustID IS NULL)) 
    AND (p.CustName = i.CustName OR (p.CustName IS NULL AND i.CustName IS NULL)) 
    AND (p.Household = i.Household OR 
     (p.Household IS NULL AND i.Household IS NULL)) 
WHERE p.CustID IS NULL 

여러 열을 비교합니다. 귀하의 컬럼 이름을 바탕으로, 나는 스키마가 제대로 정상화되었는지 궁금해하기 시작했습니다. CustID은 대부분 하나와 연관되어야합니다 CustName - 두 가지를 모두 비교해야한다는 사실은 다소 이상하게 보입니다. 그리고 Household - 나는 그것이 무엇인지 모르겠다. 그러나 그것이 varchar(x)/nvarchar(x) 컬럼이라면 고객과 1 : 1의 관계가 있는지 궁금해한다.

내가 너무 많이 추측한다면이 단락을 기각 할 수있다. 하지만 단지의 경우, 나는 그것이 훨씬 쉽고 빠르게 쿼리 할 수 ​​있도록 것입니다 정상화, 경우이 데이터가 제대로 정규화 아니라고 말하고 싶다 : 어쨌든

SELECT * 
FROM Input 
WHERE CustID NOT IN (SELECT CustID FROM Production) 

, 첫 번째 쿼리에 다시 가고, 그게 지금 우리가해야 할 일이기 때문입니다. 불행하게도 그것은 LINQ에있는 그 특정 조건에 조인을 만들 수 없다, 그래서 우리는 (2 회 우리가 지금 Input에서 읽을해야하기 때문에) 조금 더 뭔가로 SQL 쿼리를 다시 작성해야합니다

SELECT * 
FROM Input 
WHERE <Primary Key> NOT IN 
(
    SELECT i.<Primary Key> 
    FROM Input i 
    INNER JOIN Production p 
    ON (p.CustID = i.CustID OR (p.CustID IS NULL AND i.CustID IS NULL)) 
    AND (p.CustName = i.CustName OR (p.CustName IS NULL AND i.CustName IS NULL)) 
    AND (p.Household = i.Household OR 
     (p.Household IS NULL AND i.Household IS NULL)) 
) 

이제 우리는 우리가 뭔가를 마침내 Linq 구문으로 변환 할 수 있습니다. 명시 적으로 참여를 명시 적으로 수행 할 수는 없지만 이전에는 구식 가입으로 시작하여 결합 조건을 WHERE 세그먼트로 버리고 서버는 계속 정렬 할 수 있습니다 :

var excluded = 
    from i in input 
    from p in production 
    where 
     ((p.CustID == i.CustID) || ((p.CustID == null) && (i.CustID == null))) && 
     ((p.CustName == i.CustName) || 
      ((p.CustName == null) && (i.CustName == null))) && 
     ((p.Household == i.Household) || 
      ((p.Household == null) && (i.Household == null))); 
    select i.PrimaryKey; 

var results = 
    from i in input 
    where !excluded.Contains(i.PrimaryKey) 
    select i; 

여기에 테이블에 기본 키가 있다고 가정합니다. 당신이하지 않으면, 당신은 다른 문제를 가지고,하지만 당신은 사용이 특정 문제를 해결 얻을 수 EXCEPT :

var excluded = 
    from i in input 
    from p in production 
    where 
     ((p.CustID == i.CustID) || ((p.CustID == null) && (i.CustID == null))) && 
     ((p.CustName == i.CustName) || 
      ((p.CustName == null) && (i.CustName == null))) && 
     ((p.Household == i.Household) || 
      ((p.Household == null) && (i.Household == null))); 
    select i; 

var results = input.Except(excluded); 
+0

는 SQL은 두 번째 테이블에서 각 행을 반환하기 때문에 여기에 작동하지 않습니다에 가입 어디에 3 개의 열이 일치합니다. 한 줄만 있으면 돼. 열 이름은 설명을위한 것입니다. 기본 키가없고 ID 열은 관련이 없습니다. ID는 각 테이블마다 고유하므로 사용할 수 없습니다. LINQ가 나에게 몇 가지 조언을주었습니다. 감사. –

+0

@ Tony_Henrich : 오른쪽 테이블에 일치하는 행이 여러 개 있으면 올바른 것입니다. 첫 번째 쿼리는 중복 행을 반환합니다. 그러나, 필자가 쓴 후속 쿼리는 그 문제가 없을 것이며, Linq 쿼리는 원하는 것을 할 것입니다. (PK가 없다면 마지막 것을 포함 해서요.하지만 PK가 없으면 정말 좋습니다.이 예제는 좋은 것입니다.) 그들이 왜 중요한지에 대한 그림). – Aaronaught

+0

긴 이야기를 짧게하기 위해 테이블은 실제로 Excel 스프레드 시트입니다. 작업을 확인하기 위해 SQL Server에 데이터를 복사했습니다. 기본 키는 후보자가 없으므로 도움이되지 않습니다. 각 테이블의 고유 한 ID 열은 해당 테이블에 고유합니다. 테이블간에 값이 일치하지 않습니다. –

관련 문제