SQL学习之学会使用子查询

1、SELECT语句是SQL的查询。我之前的随笔中所用的SELECT语句都是简单的查询,即从单个数据库表中检索数据的单条SELECT语句。

查询:任何SQL语句都是查询,但此术语一般指SELECT语句。

2、SQL不仅允许简单的SELECT查询,还允许创建子查询,即嵌套在其他查询中的查询。

下面通过实例来了解子查询在实际项目中的应用:

create database Study
gouse Study
go
create table Customers(
Id int identity(1,1),
Name varchar(10) null
)
insert into Customers values(‘张三‘)
insert into Customers values(‘李四‘)
insert into Customers values(‘王五‘)
insert into Customers values(‘赵六‘)
insert into Customers values(‘冯七‘)
select * from Customers
create table Products(
Id int identity(1,1),
Name varchar(255) null
)
insert into Products values(‘产品一‘)
insert into Products values(‘产品二‘)
insert into Products values(‘产品三‘)
insert into Products values(‘产品四‘)
insert into Products values(‘产品五‘)
select * from Products
create table Orders(
Id int identity(1,1),
CustomerId int null,
AddDate datetime null
)
insert into Orders values(1,GETDATE())
insert into Orders values(2,GETDATE())
insert into Orders values(3,GETDATE())
insert into Orders values(4,GETDATE())
insert into Orders values(5,GETDATE())
select * from Orders
create table OrderItems
(
Id int identity(1,1),
OrderId int null,
ProductId int null
)
insert into OrderItems values(1,1)
insert into OrderItems values(1,2)
insert into OrderItems values(1,3)
insert into OrderItems values(2,3)
insert into OrderItems values(3,2)
insert into OrderItems values(4,1)
select * from OrderItems

这是分析SQL子查询所需要用到的sql文件。

这是4个表的基础数据

需求:现在我们需要列出订购产品Id为1的所有顾客,下面是基本的思路:

(1)先去OrderItems(中间表)检索产品Id为‘1‘的所有的订单编号,代码如下:

select Id,orderId from OrderItems where ProductId=1

(2)拿到(1)步骤所有的订单Id编号之后,再根据检索出来的订单Id,去Orders(订单表)查找对应的顾客Id(是那些顾客下了这些订单),代码如下:

select CustomerId from Orders where Id in (select orderId  from OrderItems where ProductId=1)

注意下面这种写法是错的:

select CustomerId from Orders where Id in (select Id,orderId  from OrderItems where ProductId=1)

这就相当于判断Id==Id,orderId这种写法是错的!

DMBS控制台报的错误信息:当没有用 EXISTS 引入子查询时,在选择列表中只能指定一个表达式。告诉你子查询中的选择列表只能指定一个表达式!

(3)拿到所有顾客Id之后,再根据这些顾客Id,去Customers(顾客表)中检索顾客的详细信息,代码如下:

select * from Customers Where Id in (select CustomerId from Orders where Id in (select orderId from OrderItems where ProductId=1))

ok!完成了上面提出的需求

但是有一点不足的是如果查询的深度很深,代码就会很长,像上面的书写代码的方式,不易于我们阅读,有如下代码:

select *
from Customers
Where Id IN(select CustomerId
            from Orders
            where Id IN(select orderId
                                    from OrderItems
                                    where ProductId=1))

这段代码层次分明,比之前的代码更加的容易理解!

3、下面是使用子查询必须知道的几点:

(1)很重要的一点,作为子查询的SELECT语句只能查询单个列。企图检索多个列将返回错误(上面列子中的第(2)步已给出证明)。

(2)子查询的性能:上面给出的列子中的代码有效,并且获得了所需的结果。但是使用子查询并不总是执行这类数据检索最有效的方法。

4、下面改变当前随笔2中的需求,需要显示Customers表中的每个顾客的订单总数。

简单分析下思路,因为Customers表中没有订单总数这个字段,所以目前我们只能用一个计算字段来代替订单总数,而这个计算字段的列值必须是每个顾客的订单总数。

(1)先从Customers表中检索出顾客列表Id

(2)对于检索出来的每个顾客,统计其在Orders表中的订单数目

一般情况下统计一个顾客在Orders(订单表)中的订单总数,可以这样做:

select count(*)  from Orders where CustomerId=1

上面代码统计了顾客编号为1的订单总数,但是这里需要统计的是所有用户的订单总数,显然这样写不对,我们可以这样写:

select name,(select COUNT(*) from Orders where Orders.CustomerId=Customers.Id) as orders from Customers

这段代码实际并不能检索出来结果,因为他将一个计算字段,被插入到其他的SELECT语句中一起被返回,该查询对对检索出的每个顾客ID执行一次 select COUNT(*) from Orders where dbo.Orders.CustomerId=当前顾客Id的运算;因为有5个顾客,所以会进行5次运算。返回每个顾客的总订单数。

下面是完整代码:

select name,(select COUNT(*) from Orders where Orders.CustomerId=Customers.Id) as orders from Customers

子查询中的WHERE子句(where Orders.CustomerId=Customers.Id)与前面使用的WHERE子句稍有不同,因为它使用了完全限定列名,而不只是列名。他指定列名和表名(Orders.CustomerId和Customers.Id),这个Where子句等于告诉SQL比较Orders的CustomerId和当前正从Customers表中检索的Id

时间: 2024-08-10 01:52:47

SQL学习之学会使用子查询的相关文章

Sql学习笔记4——嵌套子查询(下)

5)from子句中的子查询 因为SQL任何select-from-where表达式返回的都是关系,所以from子句中允许使用子查询表达式. 考虑查询“找出平均工资超过42000美元的那些系中教师的平均工资”,之前我们用having子句来书写该查询. 现在我们不用having子句,如下: select dept_name,avg_salary from(select dept_name,avg(salary) as avg_salary from instructor group by dept_

Sql学习笔记4——嵌套子查询(上)

嵌套子查询 子查询是嵌套在另一个查询中的select-from-where表达式.子查询嵌套在where子句中时,通常用于对集合的成员资格.集合的比较以及集合的基数进行检查. 1.集合成员资格 SQL允许测试元组在关系中的成员资格.连接词in测试元组是否是集合中的成员,集合是由select子句产生的一组值构成的.连接词not in测试元组是否不是集合中的成员. 考虑“找出在2009年秋季和2010年春季学期同时开课的所有课程.”按之前所学知识,可以通过对两个集合进行并运算来书写该查询.如下: (

SQL点滴10—使用with语句来写一个稍微复杂sql语句,附加和子查询的性能对比

原文:SQL点滴10-使用with语句来写一个稍微复杂sql语句,附加和子查询的性能对比 今天偶尔看到sql中也有with关键字,好歹也写了几年的sql语句,居然第一次接触,无知啊.看了一位博主的文章,自己添加了一些内容,做了简单的总结,这个语句还是第一次见到,学习了.我从简单到复杂地写,希望高手们不要见笑.下面的sql语句设计到三个表,表的内容我用txt文件复制进去,这里不妨使用上一个随笔介绍的建立端到端的package的方法将这些表导入到数据库中,具体的就不说了. 从这里下载文件employ

走向面试之经典的数据库基础:二、SQL进阶之case、子查询、分页、join与视图

一.CASE的两种用法 1.1 等值判断->相当于switch case (1)具体用法模板: CASE expression WHEN value1 THEN returnvalue1 WHEN value2 THEN returnvalue2 WHEN value3 THEN returnvalue3  ELSE defaultreturnvalue END (2)具体使用示例: 假设我们有一个论坛网站,其中有一张User表{ UId,Name,Level },Level是一个int类型,代

SQL主外键和子查询

主键 数据库主键是指表中一个列或列的组合,其值能唯一地标识表中的每一行.这样的一列或多列称为表的主键,通过它可强制表的实体完整性.当创建或更改表时可通过定义 PRIMARY KEY约束来创建主键.一个表只能有一个 PRIMARY KEY 约束,而且 PRIMARY KEY 约束中的列不能接受空值.由于 PRIMARY KEY 约束确保唯一数据,所以经常用来定义标识列. 主键的作用 主键的主要作用如下: (1)保证实体的完整性: (2)加快数据库的操作速度: (3) 在表中添加新记录时,数据库会自

SQL笔记-第八章,子查询

一.SELECT列表中的标量子查询 查询每种书籍类型中的最早出版的书籍.在SQL 查询中,需要将一本书籍的出版年份与该类型的所有书籍的出版年份进行比较,并且仅仅在它们匹配时,才返回一个记录 SELECT T_Category.FId, T_Book. FName,T_Book.FYearPublishedFROM T_CategoryINNER JOIN T_Book ON T_Category.FId=T_Book.FCategoryIdWHERE T_Book.FYearPublished=

《MySQL必知必会学习笔记》:子查询

子查询 在开始了解子查询之前,首先做下准备工作,建立3个表, 一个是customers表,其中包括:客户名字.客户ID.客户Tel等. 一个是orders表,其中包括:订单号.客户ID.订单时间等. 一个是ordersitems表,其中包括:订单物品.订单号.物品数量. 准备工作 1.建表 建customers表的命令如下,其它的表与之类似: create table customers(cust_name varchar(10),cust_id int(10),cust_tel varchar

Hive学习之Union和子查询

Union的语法格式如下: select_statement UNION ALL select_statement UNION ALL select_statement ... Union用于将多个SELECT语句的查询结果合并到一个结果集中,目前Hive只支持UNION ALL,也就是结果集中的重复记录不会被删除.SELECT语句返回列的数目和名称必须相同,否则会报schema错误.Union语句还可以嵌套在FROM子句中: SELECT * FROM ( select_statement U

SQL连接、合并、子查询

连接:连接分为内连接.外连接.交叉连接 内连接和外连接都是在笛卡尔积的基础做一些修改. 合并查询:把两个相似的结果可以用union联合起来. mysql> select id,time from exam -> union -> select id,time from recuit; +-----+------------+ | id | time | +-----+------------+ | 1 | 2016-08-30 | | 2 | 2016-09-10 | | 8 | NUL