SQL joining three tables, join precedence

后端 未结 4 490
清酒与你
清酒与你 2020-12-14 15:53

I have three tables: R, S and P.

Table R Joins with S through a foreign key; there should be at least one record in S, so I can JOIN:

SELECT         


        
相关标签:
4条回答
  • 2020-12-14 16:37
    with a as (select 1 as test union select 2)
    select * from a left join
    a as b on a.test=b.test and b.test=1 inner join
    a as c on b.test=c.test 
    go
    with a as (select 1 as test union select 2)
    select * from a inner join
    a as b on a.test=b.test  right join
    a as c on b.test=c.test and b.test=1
    

    Ideally, we would hope that the above two queries are the same. However, they are not - so anybody that says a right join can be replaced with a left join in all cases is wrong. Only by using the right join can we get the required result.

    0 讨论(0)
  • 2020-12-14 16:40

    When you join the third table, your first query

    SELECT
            *
        FROM 
            R
        JOIN    S ON (S.id = R.fks)
    

    is like a derived table to which you're joining the third table. So if R JOIN S produces no rows, then joining P will never yield any rows (because you're trying to join to an empty table).

    So, if you're looking for precedence rules then in this case it's just set by using LEFT JOIN as opposed to JOIN.

    However, I may be misunderstanding your question, because if I were writing the query, I would swap S and R around. eg.

    SELECT
            *
        FROM 
            S
        JOIN    R ON (S.id = R.fks)
    
    0 讨论(0)
  • 2020-12-14 16:44

    All kinds of outer and normal joins are in the same precedence class and operators take effect left-to-right at a given nesting level of the query. You can put the join expression on the right side in parentheses to cause it to take effect first. Remember that you have to move the ON clause of the join that is now outside the join you put parens on.

    (PostgreSQL example)

    In SELECT * FROM a LEFT JOIN b ON (a.id = b.id) JOIN c ON (b.ref = c.id);

    the a-b join takes effect first, but we can force the b-c join to take effect first by putting it in parentheses, which looks like:

    SELECT * FROM a LEFT JOIN (b JOIN c ON (b.ref = c.id)) ON (a.id = b.id);

    Often you can express the same thing without extra parentheses by moving the joins around and changing the outer join direction, e.g.

    SELECT * FROM b JOIN c ON (b.ref = c.id) RIGHT JOIN a ON (a.id = b.id);

    0 讨论(0)
  • 2020-12-14 16:53

    The second join is tied to S as you explicity state JOIN P ON (P.id = S.fkp) - no column from R is referenced in the join.

    0 讨论(0)
提交回复
热议问题