ern,如果按"b.name not in就先过滤了b表中相关内容,和a表外连接后除了有两条相等的(a表中也有的)外,再填补了a表所有内容"来解释,执行完第一段代码后应该显示a表的所有内容,可他并没显示啊.麻烦再解释解释~~~~~~~~~~~~~~
首先执行from songyh.worker a, songyh.workerskill b 语句,相当于告诉数据库中a表中的每一条数据要跟b中的每一条数据作连接。 具体执行时,从a表中选出一条记录,然后根据b表中的一条记录按着连接条件连接。 连好的记录再根据where的条件判断是否要显示。判断时就有一个先后的问题了,oracle数据库从where条件的最后条件开始,即先根据a.name not in (select name from songyh_worker_skill where skill='Smithy') 判断, 然后再根据 a.name=b.name(+)判断, 当然,如果不满足第一条,就pass了, 不必再看第二条了。这样一次判断一个“预连接”的笛卡尔积,-----最后得出结果。
你可以把你的sql语句拆开来执行 select a.name,a.age,a.lodging ,b.skill,b.ability from songyh_worker a, songyh_worker_skill b where a.name=b.name(+);select a.name,a.age,a.lodging ,b.skill,b.ability from songyh_worker a, songyh_worker_skill b where a.name not in(select name from songyh_worker_skill where skill='Smithy'); a.name=b.name(+) 其实是取出了 a.name 中全部的的数据记录就第一条sql b.name not in 其实就是限定了 b.name=Adah Talbot,Elbert Talbot,Helen Brandt,Wilfred Lowell 在这条sql 中其实 a.name=b.name(+) 就等于 a.name=b.name 也就是a.name=Adah Talbot,Elbert Talbot,Helen Brandt,Wilfred Lowell第二条 sql 是后面的 not in 限制了 a.name 的取值的范围 a.name=b.name(+) 只是限制了 数据的冗余数据不同 但理论应该是一样的 : ops$lg\[email protected] >select * from t1; N ---------- 1 2ops$lg\[email protected] >select * from t2; N2 ---------- 1 3 -- 这是我把第一个 sql 语句分开执行的语句 ops$lg\[email protected] >select t1.n,t2.n2 from t1,t2 where t1.n=t2.n2(+); 《语句1》 N N2 ---------- ---------- 1 1 2ops$lg\[email protected] >select t1.n,t2.n2 from t1,t2 where t2.n2 not in(3); 《语句2》 N N2 ---------- ---------- 1 1 2 1ops$lg\[email protected] >select t1.n,t2.n2 from t1,t2 where t1.n=t2.n2(+) and t2.n2 not in(3); -- 在这个语句中应该是上面两个语句的交集 所以只有一条结果 N N2 ---------- ---------- 1 1 你的第2条 sql 道理类似的
我认为第一个语句执行b.name not in 3* (select name from songyh_worker_skill where skill='Smithy') 时,由于一些name在第二个表中没有对应的,如Bart Sarjeant 也就是说b.name 为null,所以,就被pass了, 所以,第一个表里的数据比第二个少 不知道对吗?我这样理解
marinedalian(红袖添香) ( ) 首先执行from songyh.worker a, songyh.workerskill b 语句,相当于告诉数据库中a表中的每一条数据要跟b中的每一条数据作连接。 具体执行时,从a表中选出一条记录,然后根据b表中的一条记录按着连接条件连接。 连好的记录再根据where的条件判断是否要显示。判断时就有一个先后的问题了,oracle数据库从where条件的最后条件开始,即先根据a.name not in (select name from songyh_worker_skill where skill='Smithy') 判断, 然后再根据 a.name=b.name(+)判断, 当然,如果不满足第一条,就pass了, 不必再看第二条了。这样一次判断一个“预连接”的笛卡尔积,-----最后得出结果。drabit(square) 对NULL理解的问题: 肯定是a.name=b.name(+)先执行,但是第一个用b.name去not in,连接后b.name某些记录为null,而null作为任何条件判断是无意义的.这些记录肯定被弃掉. 连接后a.name肯定有值,所以结果记录多. 楼主 我觉得答案就是这两位仁兄的综合了 呵呵 学习了很多东西啊啊!
(select name from songyh_worker_skill where skill='Smithy') 判断, 然后再根据
a.name=b.name(+)判断, 当然,如果不满足第一条,就pass了, 不必再看第二条了。这样一次判断一个“预连接”的笛卡尔积,-----最后得出结果。
请问如何看执行计划啊???
偶刚接触oracle,呵呵!
高手继续指教啊!!!
肯定是a.name=b.name(+)先执行,但是第一个用b.name去not in,连接后b.name某些记录为null,而null作为任何条件判断是无意义的.这些记录肯定被弃掉.
连接后a.name肯定有值,所以结果记录多.
select a.name,a.age,a.lodging ,b.skill,b.ability from songyh_worker a,
songyh_worker_skill b where a.name=b.name(+);select a.name,a.age,a.lodging ,b.skill,b.ability from songyh_worker a,
songyh_worker_skill b where a.name not in(select name from songyh_worker_skill where skill='Smithy'); a.name=b.name(+) 其实是取出了 a.name 中全部的的数据记录就第一条sql b.name not in 其实就是限定了 b.name=Adah Talbot,Elbert Talbot,Helen Brandt,Wilfred Lowell 在这条sql 中其实 a.name=b.name(+) 就等于 a.name=b.name
也就是a.name=Adah Talbot,Elbert Talbot,Helen Brandt,Wilfred Lowell第二条 sql 是后面的 not in 限制了 a.name 的取值的范围 a.name=b.name(+) 只是限制了
数据的冗余数据不同 但理论应该是一样的 :
ops$lg\[email protected] >select * from t1; N
----------
1
2ops$lg\[email protected] >select * from t2; N2
----------
1
3
-- 这是我把第一个 sql 语句分开执行的语句
ops$lg\[email protected] >select t1.n,t2.n2 from t1,t2 where t1.n=t2.n2(+); 《语句1》 N N2
---------- ----------
1 1
2ops$lg\[email protected] >select t1.n,t2.n2 from t1,t2 where t2.n2 not in(3); 《语句2》 N N2
---------- ----------
1 1
2 1ops$lg\[email protected] >select t1.n,t2.n2 from t1,t2 where t1.n=t2.n2(+) and t2.n2 not in(3);
-- 在这个语句中应该是上面两个语句的交集 所以只有一条结果 N N2
---------- ----------
1 1
你的第2条 sql 道理类似的
3* (select name from songyh_worker_skill where skill='Smithy')
时,由于一些name在第二个表中没有对应的,如Bart Sarjeant 也就是说b.name 为null,所以,就被pass了,
所以,第一个表里的数据比第二个少
不知道对吗?我这样理解
如果要提高查询效率,应该是先判断,然后在进行连接啊?而不应该是先连接在判断啊?兄弟们继续探讨啊!!
响应的人太多了,分不够了!呵呵!
这种旧式的外连接(+),在加条件时,容易造成歧义。
9i后,ORACLE建议用LEFT JOIN的写法了。
用not in 时,如果 字段没有建唯一索引,查询结果可能会不准确
首先执行from songyh.worker a, songyh.workerskill b 语句,相当于告诉数据库中a表中的每一条数据要跟b中的每一条数据作连接。 具体执行时,从a表中选出一条记录,然后根据b表中的一条记录按着连接条件连接。 连好的记录再根据where的条件判断是否要显示。判断时就有一个先后的问题了,oracle数据库从where条件的最后条件开始,即先根据a.name not in
(select name from songyh_worker_skill where skill='Smithy') 判断, 然后再根据
a.name=b.name(+)判断, 当然,如果不满足第一条,就pass了, 不必再看第二条了。这样一次判断一个“预连接”的笛卡尔积,-----最后得出结果。drabit(square)
对NULL理解的问题:
肯定是a.name=b.name(+)先执行,但是第一个用b.name去not in,连接后b.name某些记录为null,而null作为任何条件判断是无意义的.这些记录肯定被弃掉.
连接后a.name肯定有值,所以结果记录多.
楼主 我觉得答案就是这两位仁兄的综合了 呵呵 学习了很多东西啊啊!