SQL Server Left Join With 'Or' Operator

前端 未结 4 1749
Happy的楠姐
Happy的楠姐 2021-01-03 19:21

I have a four tables, TopLevelParent, two mid level tables MidParentA and MidParentB, and a Child table which can have a parent of MidParentA or MidParentB (One or the other

4条回答
  •  青春惊慌失措
    2021-01-03 19:49

    Here is what I did in the end, which got the execution time down from 52 secs to 4 secs.

    SELECT * 
    FROM (
        SELECT tpl.*, a.MidParentAId as 'MidParentId', 1 as 'IsMidParentA' 
        FROM TopLevelParent tpl 
        INNER JOIN MidParentA  a ON a.TopLevelParentId = tpl.TopLevelParentID
    UNION
        SELECT tpl.*, b.MidParentBId as 'MidParentId', 0 as 'IsMidParentA'  
        FROM TopLevelParent tpl 
        INNER JOIN MidParentB b ON b.TopLevelParentId = tpl.TopLevelParentID
    UNION
        SELECT tpl.*, 0 as 'MidParentId', 0 as 'IsMidParentA'  
        FROM TopLevelParent tpl 
        WHERE tpl.TopLevelParentID NOT IN (
           SELECT pa.TopLevelParentID 
           FROM TopLevelParent tpl
           INNER JOIN MidParentA  a ON a.TopLevelParentId = tpl.TopLevelParentID
        UNION
           SELECT pa.TopLevelParentID 
           FROM TopLevelParent tpl
           INNER JOIN MidParentB b ON h.TopLevelParentId = tpl.TopLevelParentID
        )
    ) tpl
    LEFT JOIN MidParentA a ON a.TopLevelParentId = tpl.TopLevelParentID
    LEFT JOIN MidParentB b ON b.TopLevelParentId = tpl.TopLevelParentID
    LEFT JOIN 
    (
            SELECT  [ChildId]
                    ,[MidParentAId] as 'MidParentId'
                    ,1 as 'IsMidParentA'
            FROM Child c
            WHERE c.MidParentAId IS NOT NULL
       UNION
            SELECT [ChildId]
                   ,[MidParentBId] as 'MidParentId'
                   ,0 as 'IsMidParentA'
            FROM Child c
            WHERE c.MidParentBId IS NOT NULL
    ) AS c
    ON c.MidParentId = tpl.MidParentId  AND c.IsMidParentA = tpl.IsMidParentA
    

    This eliminates the table scanning that was happening, as I have matched the top level record to its midlevel parent up front if it exists, and stamped it on that record.

    I have also done the same with the child record meaning I can then just join the child record to the top level record on the MidParentId, and I use the IsMidParentA bit flag to differentiate where there are two identical MidParentIds (ie an Id of 1 for IsMidParentA and IsMidParentB).

    Thanks to all who took the time to answer.

提交回复
热议问题