LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1170|回复: 3

sql命令疑问

[复制链接]
发表于 2006-6-7 15:11:56 | 显示全部楼层 |阅读模式
select organcode,userid from tbluserprofile m1 where 5>(select count(*) from tbluserprofile m2 [color="Red"]where m1.organcode>m2.organcode)


ORGANCODE      USERID
------------           ----------
320000000401   Admin
320000000401   ba
320100000401   ba
320000000401   Sys100
320000000401   Oper100

谁能给解释下这里where 条件的比对原理


我把5改成7 :
select organcode,userid from tbluserprofile m1 where [color="Red"]7>(select count(*) from tbluserprofile m2 [color="Red"]where m1.organcode>m2.organcode)

ORGANCODE    USERID
------------         ----------
320000000401 Admin
320000000401 ba
320100000401 ba
[color="Red"]320102000401 ba
320200000401 ba
320000000401 Sys100
320000000401 Oper100

为什么结果和先前不一样 ?多了2条ba记录 。

谢谢
发表于 2006-6-8 10:52:25 | 显示全部楼层
这个是关联子查询,特点是每条记录的结果要和where后的子查询的结果比较才可以得到最后的结果
where m1.organcode>m2.organcode这是你加红色的

SELECT last_name, salary, department_id
FROM employees outer
WHERE salary >
(SELECT AVG(salary)
FROM employees
WHERE department_id =
outer.department_id);
你的稍微说起来不方便,看这个。查询的处理基本应该是这样:先得到第一行的记录的信息,然后把department_id作为条件给到where后的子查询,来比较得到该部门的平均工资
然后把这个值返回给外面的查询作为where条件来比较,如果符合条件则显示该记录
不符合则过滤

实际分析:用这个用户进去
然后执行这个脚本(这个脚本是性能调整里用到的分析sql执行步骤的脚本)
E:\oracle\ora92\rdbms\admin\utlxplan.sql
在登陆用户下建立这个脚本里的表
然后登陆改用户(session必须一样)
比如我
explain plan for
select employee_id,last_name from employees e1
where 10 > ( select count(*)  from employees e2
where e1.employee_id>e2.employee_id);


然后执行
select * from plan_table;
你可以看到这句sql是怎么给分析的步骤
我的表是默认安装时候的hr用户下的employees
分析表示这条语句要执行5步,第2步是过滤,把你后面子查询里的条件找到,然后是个全表扫描。然后再排序,最后index
分开来看第3步全表扫描,它把所有的记录都取出来然后第4步排序,然后是index动作的RANGE SCAN
这时候应该是oracle把你需要的结果给过滤出来并提取显示
你现在这样想,它先全表扫描得到是全部的结果集,并排序了。这个时候一条记录的值有了传给where后的自查询,要解决1.employee_id>e2.employee_id的问题。但是oracle怎么认的?"E2"."EMPLOYEE_ID"<:B1它只是认为里面的子查询的条件应该是比你提供的值小,然后统计符合条件的row数。employees表排序好后第一个employeeid应该是100,是表里员工号最小的,所以可以这样看sql:select count(*) from employees where employee_id <100;
结果是0,好了那么我们把结果返回,10>0吗?条件成立,提取改行并显示。
第2条是101,因为有100比它小,所以返回是1,成立,所以也显示
依次类推
你的表里数据应该也是类似的。所以把employees的表换成你的表,你执行下分析语句应该可以理解吧。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-6-9 11:05:17 | 显示全部楼层
SELECT last_name, salary, department_id
FROM employees outer
WHERE salary >
(SELECT AVG(salary)
FROM employees
WHERE department_id =
outer.department_id);

执行上面这句前我先查询了平均工资(select avg(salary) from employees),但是查出的第一条记录是小于avg(salary),其他记录都都大于avg(salary),这是为什么


SQL> select ename,sal,deptno from emp outer where sal>(select avg(sal) from emp where  deptno=outer.deptno);

ENAME             SAL     DEPTNO
---------- ---------- ----------
[color="Red"]ALLEN            1600         30
JONES            2975         20
BLAKE            2850         30
SCOTT            3000         20
KING             5000         10
FORD             3000         20
回复 支持 反对

使用道具 举报

发表于 2006-6-9 14:39:35 | 显示全部楼层
我用这个sql是来和你解释下什么是关联子查询,然后在引到你问的sql上去的。。。
你上面问的问题,执行上面这句前我先查询了平均工资(select avg(salary) from employees),但是查出的第一条记录是小于avg(salary)[/red]你如果用这个得到的答案来联系后面的关联子查询那就错了。
因为select avg(salary) from employees,它的结果是把所有的employees里的salary做了个平均值计算,而关联子查询是select avg(sal) from emp where deptno=outer.deptno[/red]
加了个where的结果是不一样了,它要求的只是里面的子查询的deptno等于外面所提供的值的记录的sal字段求平均值
如果你要看可以看这条语句select deptno,avg(salary) from employees group by deptno
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表