开发者

How can I substitute a left join in SQL

Can anyone tell me how can I write the equi开发者_运维技巧valent of a left join without really using left joins.

Select * from a left join b on a.name = b.name.


Bear in mind that SQL’s outer join is a kind of relational union which is expressly designed to project null values. If you want to avoid using the null value (a good thing, in my opinion), you should avoid using outer joins. Note that modern relational languages have dispensed with the concept of null and outer join entirely.

This outer join:

SELECT DISTINCT T1.id, T1.value, T2.other_value
  FROM T1
       LEFT OUTER JOIN T2
          ON T1.id = T2.id;

…is semantically equivalent to this SQL code:

SELECT T1.id, T1.value, T2.other_value
  FROM T1
       INNER JOIN T2
          ON T1.id = T2.id
UNION
SELECT T1.id, T1.value, NULL
  FROM T1
 WHERE NOT EXISTS (
                   SELECT * 
                     FROM T2
                    WHERE T1.id = T2.id
                  );

The second query may look long winded but that’s only because of the way SQL has been designed/evolved. The above is merely a natural join, a union and a semijoin. However, SQL has no semijoin operator, requires you to specify column lists in the SELECT clause and to write JOIN clauses if your product hasn’t implemented Standard SQL’s NATURAL JOIN syntax, which results in a lot of code to express something quite simple.

Therefore, you could write code such as the second query above but using an actual default value rather than the null value.


Although left outer joins are the recommended way of writing sql as compared to an alternative but still we can achieve left outer join by using union for the resultset. If we have two table Table1 and Table 2 then we can achieve this by the following -

select
       A.Id, 
       A.Col1, 
       A.Col2, 
       A.Col3, 
       B.Id Col4, 
       B.Col1 Col5, 
       B.Col2 Col6, 
       B.Col3 Col7, 
       B.Col4 Col8
from   Table1 A, Table2 B
where  A.Id = B.Id

union all

select
       A.Id, 
       A.Col1, 
       A.Col2, 
       A.Col3, 
       null as Col4, 
       null as Col5, 
       null as Col6, 
       null as Col7, 
       null as Col8
from   Table1 A
where  not exists(select 1 from Table2 B where B.Id = A.Id)

This will help achieve the same result but because of the use of Union there could be some performance problems in case the tables are large.


Oracle disguised left join:

SELECT * FROM A, B
 WHERE a.name = b.name(+)

Generic :

SELECT a.*, case c.existence WHEN 1 then c.name ELSE NULL END
  FROM A
 INNER JOIN ( SELECT name name, 1 existence FROM B
               UNION ALL
              SELECT a.name name, 0 existence FROM A
               WHERE a.name NOT IN ( SELECT name FROM B )
            ) C
    ON c.name = a.name
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜