2017-05-08 5 views
1

customers 테이블에는 2016 년에 1500 개의 주문이있는 총 1000 명의 고객이 있습니다.하지만 FY에 총 주문 수를 가진 모든 고객을 표시하려고합니다 고객이 그 회계 연도에 주문했는지 여부. 그러나 SQL Server 2012의 다음 쿼리는 1490 만 표시됩니다.이 LEFT OUTER JOIN이 왼쪽의 모든 기본 키를 포함하지 않는 이유

여기에 누락 된 부분은 무엇입니까?

SELECT c.CustomerID, count(*) AS TotalOrders 
FROM Customers c 
LEFT JOIN Orders o ON c.CustomerID = o.CustomerID 
WHERE o.FiscalYear = '2016' 
GROUP BY c.CustomerID 

UPDATE :

다음 쿼리는 하나 개 더 레코드 (1491)를 반환은 - 아직 9 개 이상의 레코드가 없습니다.

SELECT c.CustomerID, count(*) AS TotalOrders 
FROM Customers c 
LEFT JOIN Orders o ON c.CustomerID = o.CustomerID 
        AND o.FiscalYear = '2016' 
GROUP BY c.CustomerID 
+1

조인 후에 where 절이 적용됩니다. 따라서 조인은 주.없이 고객에 대한 널 값을 리턴합니다. 하지만 그 고객은 아무런 명령도 내리지 않고 있습니다. 회계 년도는 2016 년과 같지 않아서 레코드가 제외됩니다. 외부 조인과 관련된 제한 조건을 조인 기준으로 이동하여 조인과 함께 제한이 적용되도록 수정합니다. – xQbert

+3

총 레코드 수는 1000 (고객)이어야합니다. 합계의 수는 1500이어야합니다. 합계가 1500 미만인 유일한 차이는 고객 및 고아 주문을 삭제 한 것입니다. 또는 2016 년 주문 1500 건이 처음부터 잘못되었습니다. (고객의 고객 ID를 선택하십시오) 및 FiscalYear = '2016'이 아닌 고객 ID가 일부 레코드를 제공하는 주문에서 SELECT *를 수행합니까? – xQbert

+0

그래, 나는 다음과 같은 사항을 확인하기 시작할 것입니다 : 귀하의 FiscalYear가 실제로 모든 레코드에 대해 "2016"으로 구별됩니까? 오타가 발생할 가능성이 있습니까? 레코드가 삭제 된 것으로 표시되는 방법 (비트/int 플래그)? –

답변

6

당신 where 절은 Inner joinleft outer join를 돌고있다. AND

변경을 :

SELECT c.CustomerID, count(o.CustomerID) AS TotalOrders 
FROM Customers c 
LEFT JOIN Orders o 
    ON c.CustomerID = o.CustomerID 
    AND o.FiscalYear = '2016'  -- Here 
GROUP BY c.CustomerID 
+0

나는 'LEFT JOIN'에서'Where' 조건을 포함 시키려고했으나 총 레코드 수를 1 늘려야한다고 언급 했어야했습니다. 아직 9 개 더 부족합니다. – nam

+0

@nam 검색어가 아닙니다. 지금 Customers 테이블에 얼마나 많은 CustomerID가 있는지 확인할 수 있습니까? – GurV

+2

질의에 또 다른 실수가 있습니다. 주문이없는 고객의 경우 'COUNT (*)'는'COUNT (o.CustomerID) '또는 이와 유사한 것으로 0이 아닌 1을 계산해야합니다. –

0

올바른 SQL은 다음과 같습니다

SELECT c.CustomerID, count(o.CustomerID) AS TotalOrders, 
     sum(count(o.CustomerID)) over() as TotalTotalOrders 
FROM Customers c LEFT JOIN 
    Orders o 
    ON c.CustomerID = o.CustomerID AND o.FiscalYear = '2016' 
GROUP BY c.CustomerID; 

TotalTotalOrders 모든 주문해야한다 (또는 유효 고객 ID를 가진 사람 적어도).

0

고객이 주문했는지 여부와 상관없이 이 주문 된 연도와 관계없이 모든 고객을 나열합니다.. sum은 2016 년에 배치 된 모든 주문을 계산하고, 나머지는 무시하고, intenger를 반환합니다 (즉, null이 아님).

SELECT 
    c.CustomerID 
    ,sum(case when o.FiscalYear = '2016' then 1 else 0 end) AS TotalOrders 
FROM Customers c 
LEFT JOIN Orders o 
ON c.CustomerID = o.CustomerID 
GROUP BY c.CustomerID 
+0

어쨌든 @ Gurwinder의 대답은 잘 수행되지 않지만 요구 사항이 바뀌면 더 많은 유연성을 제공합니다. –