我想将*=
的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"
答案 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)
注意:
left (outer) join
一份TableB(使用2/4 on
条款 - 下面有更多内容)出于讨论目的,我将创建几个表和一些示例数据:
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