복붙노트

[SQL] 왜 내 왼쪽은 null을 반환하지에 가입한다?

SQL

왜 내 왼쪽은 null을 반환하지에 가입한다?

SQL 서버 2008 년, 나는 다음과 같은 쿼리를 가지고 :

select      
    c.title as categorytitle,
    s.title as subcategorytitle,
    i.title as itemtitle
from categories c
join subcategories s on c.categoryid = s.categoryid
left join itemcategories ic on s.subcategoryid = ic.subcategoryid 
left join items i on ic.itemid = i.itemid and i.siteid = 132
where (ic.isactive = 1 or ic.isactive is null)
order by c.title, s.title

나는 그들의 하위 범주의 항목을 얻기 위해 노력하고 있어요,하지만 난 여전히 범주 또는 하위 범주에 항목이없는 경우 레코드를 반환합니다. 상품이 없습니다 하위 카테고리가 반환되지 않습니다. 내가 뭘 잘못하고 있죠?

감사합니다

편집하다

두 번째로 수정 된 쿼리 및 where 절에 가입 왼쪽,하지만 여전히 널 (null)을 반환 아니에요. : /

EDIT 2

항목으로 이동 siteid 가입 떠났다. 나는이 작업을 수행 할 때 내가 예상했던 것보다 더 많은 방법 기록을 얻을. 일부 항목은 널 siteid을 가지고 있고 특정 ID를 때 난 단지를 포함하고 싶습니다.

EDIT 3

테이블 구조 :

Categories Table 
-------
CategoryID
Title

SubCategories Table
-------
SubCategoryID
CategoryID
Title

ItemCategories Table
-------
ItemCategoryID
ItemID
SubCategoryID
IsActive

Items Table 
--------
ItemID
Title
SiteID

해결법

  1. ==============================

    1.변화는 LEFT 항목 가입에 예상대로 내가 ... 내가 ... 당신의 쿼리가 작동합니다 항목을 가입 할 수 있습니다.

    변화는 LEFT 항목 가입에 예상대로 내가 ... 내가 ... 당신의 쿼리가 작동합니다 항목을 가입 할 수 있습니다.

    편집하다 당신은 널 (null)을 고려하지 않는 왼쪽이 null을 값이 있거나로 그 열을 허용 가입하기 때문에 좌, where 절에 테이블을 조인 필터링 할 수 없습니다 때 어떤 행이 일치 :

    및 i.siteid = 132 아무도 존재하지 않는 NULL의 i.siteid을 가지고 당신의 행 중 하나를 버려야합니다. 켜짐이 이동 :

    왼쪽 ic.itemid = i.itemid 및 i.siteid = 132 항목 I에 참가

    또는 WHERE 핸들 NULL을합니다

    WHERE ... AND (i.siteid = 132은 OR i.siteid가 null)

    편집 OP의 편집에 따라 3

    SET NOCOUNT ON
    DECLARE @Categories table (CategoryID int,Title varchar(30))
    INSERT @Categories VALUES (1,'Cat AAA')
    INSERT @Categories VALUES (2,'Cat BBB')
    INSERT @Categories VALUES (3,'Cat CCC')
    
    DECLARE @SubCategories table (SubCategoryID int,CategoryID int,Title varchar(30))
    INSERT @SubCategories VALUES (1,1,'SubCat AAA A')
    INSERT @SubCategories VALUES (2,1,'SubCat AAA B')
    INSERT @SubCategories VALUES (3,1,'SubCat AAA C')
    INSERT @SubCategories VALUES (4,2,'SubCat BBB A')
    
    DECLARE @ItemCategories table (ItemCategoryID int, ItemID int, SubCategoryID int, IsActive char(1))
    INSERT @ItemCategories VALUES (1,1,2,'Y')
    INSERT @ItemCategories VALUES (2,2,2,'Y')
    INSERT @ItemCategories VALUES (3,3,2,'Y')
    INSERT @ItemCategories VALUES (4,4,2,'Y')
    INSERT @ItemCategories VALUES (5,7,2,'Y')
    
    DECLARE @Items table (ItemID int, Title varchar(30), SiteID int)
    INSERT @Items VALUES (1,'Item A',111)
    INSERT @Items VALUES (2,'Item B',111)
    INSERT @Items VALUES (3,'Item C',132)
    INSERT @Items VALUES (4,'Item D',111)
    INSERT @Items VALUES (5,'Item E',111)
    INSERT @Items VALUES (6,'Item F',132)
    INSERT @Items VALUES (7,'Item G',132)
    SET NOCOUNT OFF
    

    나는 확실히 OP 후 어떤이는 siteid = 132이 질문에 주어진 경우에 가입 할 수있는 모든 정보를 반환합니다 100 % 아니에요

    SELECT
        c.title as categorytitle
            ,s.title as subcategorytitle
            ,i.title as itemtitle
            --,i.itemID, ic.SubCategoryID, s.CategoryID
        FROM @Items                          i
            LEFT OUTER JOIN @ItemCategories ic ON i.ItemID=ic.ItemID
            LEFT OUTER JOIN @SubCategories   s ON ic.SubCategoryID=s.SubCategoryID
            LEFT OUTER JOIN @Categories      c ON s.CategoryID=c.CategoryID
        WHERE i.siteid = 132
    

    산출:

    categorytitle                  subcategorytitle               itemtitle
    ------------------------------ ------------------------------ ------------------------------
    Cat AAA                        SubCat AAA B                   Item C
    NULL                           NULL                           Item F
    Cat AAA                        SubCat AAA B                   Item G
    
    (3 row(s) affected)
    

    siteid 132 =에이 일치가없는 경우에도, 모든 범주를 나열합니다

    ;WITH AllItems AS
    (
    SELECT
        s.CategoryID, ic.SubCategoryID, ItemCategoryID, i.ItemID
            ,c.title AS categorytitle, s.title as subcategorytitle, i.title as itemtitle
        FROM @Items                          i
            LEFT OUTER JOIN @ItemCategories ic ON i.ItemID=ic.ItemID
            LEFT OUTER JOIN @SubCategories   s ON ic.SubCategoryID=s.SubCategoryID
            LEFT OUTER JOIN @Categories      c ON s.CategoryID=c.CategoryID
        WHERE i.siteid = 132
    )
    SELECT
        categorytitle, subcategorytitle,itemtitle
        FROM AllItems
    UNION
    SELECT
        c.Title, s.Title, null
        FROM @Categories                     c
            LEFT OUTER JOIN @SubCategories   s ON c.CategoryID=s.CategoryID
            LEFT OUTER JOIN @ItemCategories ic ON s.SubCategoryID=ic.SubCategoryID
            LEFT OUTER JOIN AllItems         i ON c.CategoryID=i.CategoryID AND  s.SubCategoryID=i.SubCategoryID
        WHERE i.ItemID IS NULL
    ORDER BY categorytitle,subcategorytitle
    

    산출:

    categorytitle                  subcategorytitle               itemtitle
    ------------------------------ ------------------------------ ------------------------------
    NULL                           NULL                           Item F
    Cat AAA                        SubCat AAA A                   NULL
    Cat AAA                        SubCat AAA B                   Item C
    Cat AAA                        SubCat AAA B                   Item G
    Cat AAA                        SubCat AAA C                   NULL
    Cat BBB                        SubCat BBB A                   NULL
    Cat CCC                        NULL                           NULL
    
    (7 row(s) affected)
    
  2. ==============================

    2.귀하의 "WHERE"기준 출력의 "항목"행이 있어야한다 i.siteid 수단에. 당신이 쓰기에 필요하거나 넣어에 "i.siteid = 132"(i.siteid는 null 또는 i.siteid = 132입니다)하여 itemcategories이 너무 조인 작동 clause- 뭔가 "ON"

    귀하의 "WHERE"기준 출력의 "항목"행이 있어야한다 i.siteid 수단에. 당신이 쓰기에 필요하거나 넣어에 "i.siteid = 132"(i.siteid는 null 또는 i.siteid = 132입니다)하여 itemcategories이 너무 조인 작동 clause- 뭔가 "ON"

    select      
        c.title as categorytitle,
        s.title as subcategorytitle,
        i.title as itemtitle
    from categories c
    join subcategories s on c.categoryid = s.categoryid
    left join itemcategories ic on s.subcategoryid = ic.subcategoryid and ic.isactive = 1
    left join items i on ic.itemid = i.itemid and i.siteid = 132
    order by c.title, s.title
    
  3. ==============================

    3.어쩌면이 왼쪽에 가입해야한다 또한 가입?

    어쩌면이 왼쪽에 가입해야한다 또한 가입?

    join items i on ic.itemid = i.itemid and i.siteid = 132
    

    편집하다:

    지금 당신은 where 절에서만 기존 사이트 ID를 선택하는 :

    i.siteid = 132
    

    그것은 널 (null) 값이이 같은 시도 허용해야한다 :

    (i.siteid = 132 or i.siteid is null)
    

    조인 조건에 또는 당신이 i.siteid = (132) 등을 움직일 수

  4. ==============================

    4.

    where (ic.isactive = 1 or ic.isactive is null) and i.siteid = 132
    

    당신의 위치를 ​​왼쪽으로하고 절 기본적으로 무효화합니다 항목에 가입에 i.siteID = 132을 가졌어요.

  5. ==============================

    5.두번째 시도는, 내가 지금 당신의 문제를 가지고 생각합니다. 그때 제대로 이해한다면 무슨 일이 귀하의 경우 SiteID에 널 (NULL)의 두 종류로 끝날 것입니다 (당신이 10,000e 결과를 볼 때 경우, 그러나 그것은 바른 길에 아직도있다).

    두번째 시도는, 내가 지금 당신의 문제를 가지고 생각합니다. 그때 제대로 이해한다면 무슨 일이 귀하의 경우 SiteID에 널 (NULL)의 두 종류로 끝날 것입니다 (당신이 10,000e 결과를 볼 때 경우, 그러나 그것은 바른 길에 아직도있다).

    왼쪽에서 오는 NULL을 가입하고 실제 항목 테이블 siteid에서 온 사람이있다. 당신은 왼쪽에서 오는에 가입하지만, 데이터로부터 사람을 원하지 않는 사람을 갖고 싶어.

    이 일치하는 행의 존재 여부를 테스트 할 때 외부와 매우 일반적인 실수 조인입니다.

    당신은 항상에만 NOT NULL로 정의 된 컬럼에 NULL에 대한 테스트해야 타의 추종을 불허하는 행을하려는 경우 (외부 테이블에서 기본 키 여기에 자연 후보) 있음을 유의하십시오. 그렇지 않으면 당신은 내부 조인 경우에도 NULL이 될 것입니다 때문에 왼쪽에 NULL되는 행에 가입하고 행을 구별 할 수 없습니다

    이것에 대해 갈 적어도 두 가지 방법 : 왼쪽은 차기에 합류하기 전에 널 (null)은 a) siteid으로 행 걸러 부질 조인 남겨진 (항목 ID)의 항목에서 요구되었다고 가정 b) 재 기준 말하고

    select      
        c.title as categorytitle,
        s.title as subcategorytitle,
        i.title as itemtitle
    from categories c
    join subcategories s on c.categoryid = s.categoryid
    left join itemcategories ic on s.subcategoryid = ic.subcategoryid 
    left join items i on ic.itemid = i.itemid
    where (ic.isactive = 1 or ic.isactive is null) AND (i.siteid = 132 or i.itemid is null)
    order by c.title, s.title
    

    (I 테이블이 예상 무엇을 제공 한 최대 쿼리 항목에 참여한다고 가정하고).

    상품 ID는 항목에 필요한 경우 위의 조건을 말한다 - 정말 타의 추종을 불허 왼쪽에서 오는 siteid (132) 또는 행과 행이 조인 (i.itemid가 null이 아닌 i.siteid가 null의 조건이라고 메모를 할).

  6. ==============================

    6.뿐만 아니라이 왼쪽에있는 항목의 조인 조인 변경해보십시오.

    뿐만 아니라이 왼쪽에있는 항목의 조인 조인 변경해보십시오.

  7. from https://stackoverflow.com/questions/2479650/why-is-my-left-join-not-returning-nulls by cc-by-sa and MIT license