JOIN 子句与 WHERE 子句的比较
JOIN Clauses compared to WHERE Clauses
当我 运行 以下两个查询时,我得到了两个不同的答案。我真的很想知道为什么。是左连接吗?是操作顺序吗?这会发生在其他 JOIN 类型中吗?
第一次查询
SELECT
First_Name
, E.Employee_ID
, I.Employee_REF_ID
FROM Employee AS E
LEFT JOIN Incentives AS I
ON (E.Employee_ID = I.Employee_REF_ID) AND (I.Employee_Ref_Id IS NOT NULL);
输出
1. First_Name Employee_ID Employee_REF_ID
2. John 1 1
3. John 1 1
4. Michael 2 2
5. Michael 2 2
6. Roy 3 3
7. Tom 4 NULL
8. Jerry 5 NULL
9. NULL 6 NULL
10. TestName1 7 NULL
11. Lname% 8 NULL
第二次查询
SELECT
First_Name
, E.Employee_ID
, I.Employee_REF_ID
FROM Employee AS E
LEFT JOIN Incentives AS I
ON (E.Employee_ID = I.Employee_REF_ID)
WHERE I.Employee_Ref_Id IS NOT NULL;
输出
1. First_Name Employee_ID Employee_REF_ID
2. John 1 1
3. Michael 2 2
4. Roy 3 3
5. John 1 1
6. Michael 2 2
原始代码来自 http://narendra86.blogspot.com/2013/10/top-80-sql-query-interview-questions.html
JOIN
允许您根据您设置的条件 link 第二个 table 到第一个。
在您的第一个查询中,
如果没有匹配项,LEFT JOIN
将为您提供加入 table NULL
的所有列。
在您的第二个查询中,您的 WHERE
子句进一步删除了那些不匹配的记录,因此没有包含 NULL
.
的记录
如果您能提供有关 table 的示例数据,我们会给您更好的解释。
您应该使用 ORDER BY 子句来强制执行您想要的顺序。例如:
SELECT
First_Name
, E.Employee_ID
, I.Employee_REF_ID
FROM Employee AS E
LEFT JOIN Incentives AS I
ON (E.Employee_ID = I.Employee_REF_ID) AND (I.Employee_Ref_Id IS NOT NULL)
ORDER BY First_Name ASC;
以此为例:
declare @table1 table (emp_id int, name varchar(10))
declare @table2 table (emp_ref_id int, ref_name varchar(10))
insert into @table1 values (1, 'emp1'), (2, 'emp2'), (3, 'emp3')
insert into @table2 values (1, 'empref1'), (2, 'empref2')
这个查询:
select *
from @table1 t1
left join @table2 t2 on t1.emp_id = t2.emp_ref_id and t2.emp_ref_id is not null
returns:
emp_id name emp_ref_id ref_name
1 emp1 1 empref1
2 emp2 2 empref2
3 emp3 NULL NULL
但是这个查询:
select *
from @table1 t1
left join @table2 t2 on t1.emp_id = t2.emp_ref_id
where t2.emp_ref_id is not null
returns:
emp_id name emp_ref_id ref_name
1 emp1 1 empref1
2 emp2 2 empref2
不同之处在于,在第一个查询中,t2.emp_ref_id is not null
条件没有效果,因为它是左联接,所以即使右 table 没有匹配的行,那些列将 returned 为空。在第二个查询中,条件 t2.emp_ref_id is not null
根据查询中的 return 进行检查,因此它会删除带有 null
emp_ref_id.
的行
另一个例子:
declare @table1 table (emp_id int, name varchar(10))
declare @table2 table (emp_ref_id int, ref_name varchar(10), col3 varchar)
insert into @table1 values (1, 'emp1'), (2, 'emp2'), (3, 'emp3')
insert into @table2 values (1, 'empref1', 'a'), (2, 'empref2', null)
select *
from @table1 t1
left join @table2 t2 on t1.emp_id = t2.emp_ref_id and t2.col3 is not null
将return:
emp_id name emp_ref_id ref_name col3
1 emp1 1 empref1 a
2 emp2 NULL NULL NULL
3 emp3 NULL NULL NULL
如果您使用此查询:
select *
from @table1 t1
left join @table2 t2 on t1.emp_id = t2.emp_ref_id
它returns:
emp_id name emp_ref_id ref_name col3
1 emp1 1 empref1 a
2 emp2 2 empref2 NULL
3 emp3 NULL NULL NULL
正如你所看到的,因为它是一个左连接,当你有条件and t2.col3 is not null
时,它只是意味着左连接无法从@table2中找到匹配的行,但仍然 return 来自 table2 的行,具有空值。
由于 Left join
的计算方式不同,您的结果不同 - 在 ON
子句中使用条件与在 WHERE
子句中使用等效条件可能会产生不同的结果(当你有 ON
子句时 - 当没有匹配时我们在右侧得到 NULL
但在 WHERE
子句中,行被过滤掉)。
查看此 Whosebug 答案以获取更多详细信息 - SQL join: where clause vs. on clause
当我 运行 以下两个查询时,我得到了两个不同的答案。我真的很想知道为什么。是左连接吗?是操作顺序吗?这会发生在其他 JOIN 类型中吗?
第一次查询
SELECT
First_Name
, E.Employee_ID
, I.Employee_REF_ID
FROM Employee AS E
LEFT JOIN Incentives AS I
ON (E.Employee_ID = I.Employee_REF_ID) AND (I.Employee_Ref_Id IS NOT NULL);
输出
1. First_Name Employee_ID Employee_REF_ID
2. John 1 1
3. John 1 1
4. Michael 2 2
5. Michael 2 2
6. Roy 3 3
7. Tom 4 NULL
8. Jerry 5 NULL
9. NULL 6 NULL
10. TestName1 7 NULL
11. Lname% 8 NULL
第二次查询
SELECT
First_Name
, E.Employee_ID
, I.Employee_REF_ID
FROM Employee AS E
LEFT JOIN Incentives AS I
ON (E.Employee_ID = I.Employee_REF_ID)
WHERE I.Employee_Ref_Id IS NOT NULL;
输出
1. First_Name Employee_ID Employee_REF_ID
2. John 1 1
3. Michael 2 2
4. Roy 3 3
5. John 1 1
6. Michael 2 2
原始代码来自 http://narendra86.blogspot.com/2013/10/top-80-sql-query-interview-questions.html
JOIN
允许您根据您设置的条件 link 第二个 table 到第一个。
在您的第一个查询中,
如果没有匹配项,LEFT JOIN
将为您提供加入 table NULL
的所有列。
在您的第二个查询中,您的 WHERE
子句进一步删除了那些不匹配的记录,因此没有包含 NULL
.
如果您能提供有关 table 的示例数据,我们会给您更好的解释。
您应该使用 ORDER BY 子句来强制执行您想要的顺序。例如:
SELECT
First_Name
, E.Employee_ID
, I.Employee_REF_ID
FROM Employee AS E
LEFT JOIN Incentives AS I
ON (E.Employee_ID = I.Employee_REF_ID) AND (I.Employee_Ref_Id IS NOT NULL)
ORDER BY First_Name ASC;
以此为例:
declare @table1 table (emp_id int, name varchar(10))
declare @table2 table (emp_ref_id int, ref_name varchar(10))
insert into @table1 values (1, 'emp1'), (2, 'emp2'), (3, 'emp3')
insert into @table2 values (1, 'empref1'), (2, 'empref2')
这个查询:
select *
from @table1 t1
left join @table2 t2 on t1.emp_id = t2.emp_ref_id and t2.emp_ref_id is not null
returns:
emp_id name emp_ref_id ref_name
1 emp1 1 empref1
2 emp2 2 empref2
3 emp3 NULL NULL
但是这个查询:
select *
from @table1 t1
left join @table2 t2 on t1.emp_id = t2.emp_ref_id
where t2.emp_ref_id is not null
returns:
emp_id name emp_ref_id ref_name
1 emp1 1 empref1
2 emp2 2 empref2
不同之处在于,在第一个查询中,t2.emp_ref_id is not null
条件没有效果,因为它是左联接,所以即使右 table 没有匹配的行,那些列将 returned 为空。在第二个查询中,条件 t2.emp_ref_id is not null
根据查询中的 return 进行检查,因此它会删除带有 null
emp_ref_id.
另一个例子:
declare @table1 table (emp_id int, name varchar(10))
declare @table2 table (emp_ref_id int, ref_name varchar(10), col3 varchar)
insert into @table1 values (1, 'emp1'), (2, 'emp2'), (3, 'emp3')
insert into @table2 values (1, 'empref1', 'a'), (2, 'empref2', null)
select *
from @table1 t1
left join @table2 t2 on t1.emp_id = t2.emp_ref_id and t2.col3 is not null
将return:
emp_id name emp_ref_id ref_name col3
1 emp1 1 empref1 a
2 emp2 NULL NULL NULL
3 emp3 NULL NULL NULL
如果您使用此查询:
select *
from @table1 t1
left join @table2 t2 on t1.emp_id = t2.emp_ref_id
它returns:
emp_id name emp_ref_id ref_name col3
1 emp1 1 empref1 a
2 emp2 2 empref2 NULL
3 emp3 NULL NULL NULL
正如你所看到的,因为它是一个左连接,当你有条件and t2.col3 is not null
时,它只是意味着左连接无法从@table2中找到匹配的行,但仍然 return 来自 table2 的行,具有空值。
由于 Left join
的计算方式不同,您的结果不同 - 在 ON
子句中使用条件与在 WHERE
子句中使用等效条件可能会产生不同的结果(当你有 ON
子句时 - 当没有匹配时我们在右侧得到 NULL
但在 WHERE
子句中,行被过滤掉)。
查看此 Whosebug 答案以获取更多详细信息 - SQL join: where clause vs. on clause