使用两个别名和两个比较正确地将* =转换为LEFT OUTER JOIN

时间:2017-10-09 06:44:06

标签: sql syntax left-join sybase outer-join

我想将*=的SQL语法转换为LEFT OUTER JOIN。这是原始语法:

SELECT 
    a.col1,
    a.col2,
    b.col1,
    b.col2,
    b.col3,
    b.col4
FROM
    tableA AS a,
    tableB AS b
WHERE 
    a.col1 *= b.col1 AND
    a.col2 *= b.col2 AND
    b.col3 = "xxx"
    b.col4 = "yyy"

我正在尝试以下操作,但由于连接,它会返回太多行。我做错了什么?

SELECT 
    a.col1,
    a.col2,
    b.col1,
    b.col2,
    b.col3,
    b.col4
FROM
    tableA AS a
LEFT OUTER JOIN tableB AS b ON a.col1 = b.col1
LEFT OUTER JOIN tableB ON a.col2 = b.col2   
WHERE 
    b.col3 = "xxx"
    b.col4 = "yyy"

5 个答案:

答案 0 :(得分:2)

尝试以下示例代码

SELECT a.col1, a.col2, b.col1, b.col2, b.col3, b.col4
FROM tableA AS a
LEFT OUTER JOIN tableB AS b ON a.col1 = b.col1 AND a.col2 = b.col2
WHERE 
b.col3 = "xxx" AND b.col4 = "yyy"

答案 1 :(得分:0)

您可以在AND语法中使用JOIN

SELECT 
    a.col1,
    a.col2,
    b.col1,
    b.col2,
    b.col3,
    b.col4
FROM
    tableA AS a

LEFT OUTER JOIN tableB AS b ON a.col1 = b.col1 AND a.col2 = b.col2   
WHERE 
    b.col3 = "xxx"
    b.col4 = "yyy"

答案 2 :(得分:0)

一个LEFT JOIN就够了。你能试试吗

SELECT 
    a.col1,
    a.col2,
    b.col1,
    b.col2,
    b.col3,
    b.col4
FROM
    tableA AS a
    LEFT OUTER JOIN tableB AS b ON a.col1 = b.col1 AND a.col2 = b.col2 
WHERE 
    b.col3 = "xxx"
    AND b.col4 = "yyy"

答案 3 :(得分:0)

您的第一个查询仅涉及两个表的一个左连接,因为涉及同一对别名的所有*=比较都用于一个左连接。所以我们将它们收集到一个left join的{​​{1}}。

如果只有一对表在on中加入,则非from表的列与常量的比较也是左连接标准的一部分。所以它也在*

  

在左连接中,外表和内表是左表和右表   分别

  

如果您从外部联接的内部表中提交具有外部联接和资格的查询,则结果可能与您的预期不符。查询中的限定不限制返回的行数,而是影响哪些行包含空值。对于不符合限定条件的行,这些行的内部表的列中会显示空值。

这给出了:

on

有关完整语义,请参阅Transact-SQL® Users Guide for Adaptive Server® Enterprise 15.7。对于某些多连接查询,特别是SELECT a.col1, a.col2, b.col1, b.col2, b.col3, b.col4 FROM tableA AS a LEFT OUTER JOIN tableB AS b ON a.col1 = b.col1 AND a.col2 = b.col2 AND b.col3 = "xxx" ??? b.col4 = "yyy" 左连接语义从版本12.0开始更改。

答案 4 :(得分:0)

注意:

  • 正如philipxy所说,提供minimal, complete and verifiable example对解决你的问题有很大帮助;特别是我们不知道您的源数据是什么样的,您当前正在接收的结果,以及您想要生成的结果(所以像“给出完全相同的结果”这样的评论对我们来说没有任何意义,因为我们没有示例去)
  • 正如其他人所提到的,你只需要left (outer) join一份TableB(使用2/4 on条款 - 下面有更多内容)
  • 您没有提到使用哪种 Sybase RDBMS产品,所以我假设您正在使用Sybase ASE

出于讨论目的,我将创建几个表和一些示例数据:

use tempdb
go

if object_id('tableA') is not NULL drop table tableA
go

if object_id('tableB') is not NULL drop table tableB
go

create table tableA
(col1   int
,col2   int
)
go

insert tableA values (1,1)
insert tableA values (1,2)
insert tableA values (2,3)
insert tableA values (2,4)
go

create table tableB
(col1   int
,col2   int
,col3   varchar(10)     null
,col4   varchar(10)     null
)
go

insert tableB values (1,1,'xxx','yyy')
insert tableB values (1,2,null,null)
go

使用旧的联接外部联接方式(即*==*),在联接操作期间应用所有where子句,给出以下结果:

select  a.col1,
        a.col2,
        b.col1,
        b.col2,
        b.col3,
        b.col4

from    tableA AS a,
        tableB AS b

where   a.col1 *= b.col1
and     a.col2 *= b.col2
and     b.col3  = "xxx"
and     b.col4  = "yyy"
go

 col1        col2        col1        col2        col3       col4
 ----------- ----------- ----------- ----------- ---------- ----------
           1           1           1           1 xxx        yyy
           1           2        NULL        NULL NULL       NULL
           2           3        NULL        NULL NULL       NULL
           2           4        NULL        NULL NULL       NULL

当第一个tableA记录根据a)找到匹配时,2搜索参数(SARG)子句(col3 = xxx,col4 = yyy)和b)连接子句......其他3 {{ 1}}记录找不到匹配项(主要是由于2个SARG子句没有匹配)所以所有 tableA列都填入了NULL。

我们可以使用以下tableB样式查询生成相同的结果集:

left (outer) join

同样,SARG条款作为加入操作的一部分应用。

现在,如果目标是在之后应用的SARG条款,那么我们需要将SARG移到单独的select a.col1, a.col2, b.col1, b.col2, b.col3, b.col4 from tableA as a left join tableB as b on a.col1 = b.col1 and a.col2 = b.col2 and b.col3 = "xxx" and b.col4 = "yyy" go col1 col2 col1 col2 col3 col4 ----------- ----------- ----------- ----------- ---------- ---------- 1 1 1 1 xxx yyy 1 2 NULL NULL NULL NULL 2 3 NULL NULL NULL NULL 2 4 NULL NULL NULL NULL 子句中;要看看它是如何工作的,我们将首先使用join子句运行查询(即删除SARG子句):

where

通过将SARG子句作为单独的select a.col1, a.col2, b.col1, b.col2, b.col3, b.col4 from tableA as a left join tableB as b on a.col1 = b.col1 and a.col2 = b.col2 go col1 col2 col1 col2 col3 col4 ----------- ----------- ----------- ----------- ---------- ---------- 1 1 1 1 xxx yyy 1 2 1 2 NULL NULL 2 3 NULL NULL NULL NULL 2 4 NULL NULL NULL NULL 子句应用,我们现在只能过滤掉我们想要的行(即col3 = xxx和col4 = yyy),如下所示:

where

所以,在这一点上,我们可以看到有几个不同的结果集可以从select a.col1, a.col2, b.col1, b.col2, b.col3, b.col4 from tableA as a left join tableB as b on a.col1 = b.col1 and a.col2 = b.col2 -- apply the SARGs **after** the join: where b.col3 = "xxx" and b.col4 = "yyy" go col1 col2 col1 col2 col3 col4 ----------- ----------- ----------- ----------- ---------- ---------- 1 1 1 1 xxx yyy 查询样式生成...结果是'正确'将取决于你最终的结果是什么试图生成...回到关于提供minimal, complete and verifiable example

的评论