`

子查询转化为连接查询的例子

阅读更多
引用
   我们进行数据查询的时候极少有可能就在一张表里就能得到想要的数据,不可避免得会用到子查询或者连接查询,很多时候我们很轻松自然得会想到子查询的方法,但是子查询往往效率比较低,而转换成连接查询是一种很好的优化方式。

    子查询转换成连接查询又可以分为两种情况,一种是不带聚合的子查询转换,另一种就是带有聚合函数的转换

一、不带聚合函数的子查询转换:

以下是一组测试数据:
Sql代码  
use mytest;   
drop table  if exists jobs;   
CREATE TABLE jobs(   
    employee varchar(30),   
    title varchar(30)   
);   
drop table if exists ranks;   
CREATE TABLE ranks(   
    title varchar(30),   
    rank varchar(30)   
);   
drop table if exists salary;   
CREATE TABLE salary(   
    rank varchar(30),   
    payment int(11)   
);   
  
insert into jobs values('张三','经理'),('李四','总经理'),('王五','总经理助理');   
insert into ranks values('经理','三'),('总经理','一'),('总经理助理','二');   
insert into salary values('一',20000),('二',8000),('三',7000),('四',7000);  

use mytest;
drop table  if exists jobs;
CREATE TABLE jobs(
	employee varchar(30),
	title varchar(30)
);
drop table if exists ranks;
CREATE TABLE ranks(
	title varchar(30),
	rank varchar(30)
);
drop table if exists salary;
CREATE TABLE salary(
	rank varchar(30),
	payment int(11)
);

insert into jobs values('张三','经理'),('李四','总经理'),('王五','总经理助理');
insert into ranks values('经理','三'),('总经理','一'),('总经理助理','二');
insert into salary values('一',20000),('二',8000),('三',7000),('四',7000);


   建立了三个表,分别是jobs员工工作表,记录了员工的工作,第二表ranks是岗位等级表,记录每一个工作岗位的等级,第三个表slary自然就是HR为每一个等级的定的薪资标准了。

    现在要知道张三的工资是多少,就需要使用三张表才能得到数据,
使用子查询的方法如下:

Sql代码  
select payment from salary    
    where rank=(   
        SELECT rank from ranks    
            where title=(   
                SELECT title from jobs    
                    where employee='张三')   
);  

select payment from salary 
	where rank=(
		SELECT rank from ranks 
			where title=(
				SELECT title from jobs 
					where employee='张三')
);

转换为连接查询的步骤大致有如下几点:
1、使用表名或者表别名标记所有的列,如显jobs.employee 或者j.employee;
2、将几个子查询的From子名中使用的相同的表用同一个名字或同一别名;
3、将几个Form子句放在一起;
4、将Select及查询的列删除;
5、将第一个之后的Where替换成AND

最后得到如下结果:
Sql代码  
select payment from salary s,ranks r,jobs j    
    where j.employee='张三'    
        and j.title = r.title    
        and s.rank = r.rank;  

select payment from salary s,ranks r,jobs j 
	where j.employee='张三' 
		and j.title = r.title 
		and s.rank = r.rank;

对于需要排除某些条件的查询,如查询岗位等级表中在薪资表中没有工资级别的等级:
Java代码  
select salary.rank    
    from salary    
        where rank    
            not in(select rank from ranks);  

select salary.rank 
	from salary 
		where rank 
			not in(select rank from ranks);

使用not in、exists、not exists不失为一种好方法,但同样可以转换成连接查询。如以上的查询可以转换为:
Sql代码  
select salary.rank    
    from salary left join ranks    
        on salary.rank=ranks.rank    
            where ranks.rank is null;  

select salary.rank 
	from salary left join ranks 
		on salary.rank=ranks.rank 
			where ranks.rank is null;

二、带聚合函数的子查询向连接查询转换

如下测试数据,有一个订单表,记录了销售人员每天的销售记录,测试数据如下:
Sql代码  
  
DROP TABLE if exists orders;   
create table orders(   
    customer varchar(30),   
    whn date,   
    totalitems int(11)   
);   
insert into orders values('jj','2010-10-10',5),   
            ('jj','2010-10-11',3),   
            ('jj','2010-10-12',1),   
            ('aa','2010-10-10',5),   
            ('bb','2010-10-10',8),   
            ('cc','2010-10-10',10);  


DROP TABLE if exists orders;
create table orders(
	customer varchar(30),
	whn date,
	totalitems int(11)
);
insert into orders values('jj','2010-10-10',5),
			('jj','2010-10-11',3),
			('jj','2010-10-12',1),
			('aa','2010-10-10',5),
			('bb','2010-10-10',8),
			('cc','2010-10-10',10);

需要查询每一个销售员最高销售额的日期及销售额时,必然用的聚合函数MAX,以下是最容易想到的查询方式:
Sql代码  
select customer,whn,totalitems    
    from orders o1 where o1.totalitems=(   
        SELECT max(totalitems)    
            from orders o2    
                where o1.customer = o2.customer   
);  

select customer,whn,totalitems 
	from orders o1 where o1.totalitems=(
		SELECT max(totalitems) 
			from orders o2 
				where o1.customer = o2.customer
);

此时需要对每一行订单都要进行子查询,因此代码运行速度会很慢,并且老版本的MySQL还不支持子查询,只有一个表,要改成连接查询自然就是自连接了,这里我们需要使用Having子句,
Sql代码  
select o1.* from orders o1 join orders o2    
    on(o1.customer=o2.customer)    
        group by o1.customer    
            having o1.totalitems=max(o2.totalitems   
);  

select o1.* from orders o1 join orders o2 
	on(o1.customer=o2.customer) 
		group by o1.customer 
			having o1.totalitems=max(o2.totalitems
);

相信这些我们大学的时候都已经学过,但是没有真正用起来的时候总是那么容易忘记,没有实际操作和体验是感觉不到它的需要,自然也不长记性了,而写下来又是另一种记住的方式。
分享到:
评论

相关推荐

    关系代数中“除法”运算与SQL中带有exists子查询的对比教学.pdf

    关系代数中除法运算与SQL中exists子查询之间的联系,其实在某些特定的查询场景下,关系代数的除法运算可以转化为SQL中的exists子查询。例如,当你需要找出满足某些条件的主表记录,且这些记录必须关联到子表中所有...

    SQL嵌套查询实践材料

    在提供的"嵌套查询实验报告"中,很可能是包含了一些关于如何使用嵌套查询解决实际问题的例子,比如题目可能要求根据子查询的结果来筛选数据,或者通过嵌套查询找出满足特定条件的关联信息。这些练习有助于深化对嵌套...

    MYSQL子查询和嵌套查询优化实例解析

    优化方法是将子查询转化为JOIN操作,如下所示: ```sql SELECT ps.* FROM cdb_playsgame ps JOIN ( SELECT ps1.uid, ps1.gametag, MAX(credits) as credits FROM cdb_playsgame ps1 GROUP BY uid, gametag ) t ...

    浅谈MySQL中的子查询优化技巧

    1. **避免子查询的延迟执行**:如果可能,尝试将子查询转化为JOIN操作,MySQL在处理JOIN时往往有更好的优化策略。 2. **使用临时表**:在大型数据集上,将子查询结果存入临时表,然后再进行主查询,有时可以提高性能...

    oracle行列转换例子

    这里的`WHERE`条件是通过子查询实现的,它限定了`info_id`的范围,只包含分类ID为'1456'的信息。 4. **GROUP BY子句**:用于分组数据。在这里,数据按照`info_id`进行分组,这是行列转换的基础,确保每个`info_id`...

    C#.net_经典编程例子400个

    165 实例113 波形图的绘制 166 4.2 图形转换 168 实例114 BMP转换成JPG格式 168 实例115 JPG转换成BMP格式 170 实例116 位图转化为WMF 171 实例117 Ico文件转化为位图 172 实例118...

    易语言SQL查询通用例程.zip易语言项目例子源码下载

    在易语言中,我们需要了解如何通过SQL语句进行数据的增删改查操作,如SELECT、INSERT、UPDATE、DELETE等,以及更复杂的联接(JOIN)、子查询、聚合函数(COUNT、SUM、AVG等)等概念。 3. **数据库连接**:在易语言...

    第15讲数据库查询处理与优化.ppt

    如Q1和Q2的分析树分别展示了连接查询和子查询的结构。对于Q1,语法分析树显示了两个关系S和SC的连接条件,而对于Q2,它展示了一个外层查询和内层子查询的关系。 在“学生-课程”数据库中,查询选修了“c02”课程的...

    MySQL数据库存取例子代码.zip

    8. **性能优化**:了解索引、JOIN操作、子查询、存储过程等高级概念,可以帮助提升数据库的查询性能。同时,合理设计数据库架构,避免冗余数据,也是优化的重要方面。 这个压缩包中的代码实例将帮助初学者更好地...

    Linq to SQL 例子

    此外,`Linq to SQL`还支持其他操作符,如`Select`(选择元素)、`Join`(连接数据)、`GroupBy`(分组数据)、`OrderBy`(排序)等,以及更复杂的查询表达式,如联接、子查询、聚合函数等。通过组合这些操作符,...

    mysql,查询,索引

    这些索引通过不断缩小数据范围来精确找到目标数据,将原本的随机查询转化为有序查找。在数据库中,索引同样扮演着类似的角色,面对多种查询条件(如等值查询、范围查询等),索引的设计至关重要。 #### 三、磁盘I/O...

    Oracle 10G - Sql Optimization (Jonathan Lewis)

    2. **子查询的非嵌套化(Unnesting)**:子查询可以转化为内联视图或抗或半连接,这种转化可能由优化器自动完成,也可能需要手动操作。然而,有时非嵌套化并非最佳选择,存在其他更优方案。 3. **相关子查询案例...

    Android通过jsp连接Oracle数据库 -- 实例.docx

    在这个例子中,我们创建了名为`TONGXIN081`的XML元素,包含`ID`、`NAME`、`AGE`和`SEX`子元素,分别存储查询结果中的相应字段。 6. **关闭资源**:在处理完数据后,记得关闭`ResultSet`、`Statement`和`Connection`...

    一个简单的NHibernate例子

    通过ORM,我们可以将数据库中的表格映射为对象,将查询转化为对象操作,从而降低系统的复杂性。 NHibernate的核心组件包括配置、会话工厂和会话。配置文件(通常为hibernate.cfg.xml)用于定义数据库连接参数,如...

    从数据库中加载树和动态添加树的节点例子

    在读取数据的同时,将数据转化为`TreeNode`对象。`TreeNode`对象代表树形视图中的一个节点,可以通过设置其`Text`属性显示文本,通过`Tag`属性存储额外信息,如数据库记录的ID。如果查询结果包含父子关系,可以使用`...

    Hibernate查询语句教程a

    - **子查询**:可以在HQL中嵌套查询,如`from Cat as cat where cat.id in (select dog.id from Dog as dog)`。 HQL的灵活性和面向对象的特性使得它成为在Hibernate中进行复杂查询的理想选择。通过理解和熟练使用...

    oracle查询成树状

    在Oracle数据库中,将查询结果转化为树状结构是一项高级而实用的技能,尤其适用于处理具有层级关系的数据,如产品分类、组织架构等。本篇将深入解析如何利用Oracle的特定功能,实现数据的树状展示。 ### 核心概念:...

    HIBERNATE例子

    Hibernate 是一个开源的对象关系映射(ORM)框架,它允许Java开发者将数据库操作转化为对对象的操作,极大地简化了Java应用程序中的数据访问层。在“HIBERNATE例子”中,我们将探讨Hibernate的核心概念、基本配置...

    电子菜单2011

    "电子菜单2011"项目就是一个典型的例子,它将传统的纸质菜单转化为数字化形式,利用C#编程语言和SQLite数据库管理系统构建了一个高效、便捷的查询系统。这一创新不仅提升了顾客的用餐体验,也为企业后台管理提供了...

Global site tag (gtag.js) - Google Analytics