SQL子查询:在一个表表达中可以调用另一个表表达式,这个被调用的表表达式叫做子查询(subquery)
- 子查询必须放在小括号中
- 子查询一般放在比较操作符的右边,以增强代码可读性
- 子查询(小括号里的内容)可出现在几乎所有的SELECT子句中(如:SELECT子句、FROM子句、WHERE子句、ORDER BY子句、HAVING子句……)
子查询分类:
- 按方式分类: 嵌套子查询 与 相关子查询
嵌套子查询的执行不依赖与外部的查询,而相关查询则依赖
嵌套子查询示例:(查询Book表中价格小所有于图书平均价格的图书的信息)
SELECT *
FROM Books
WHERE 价格 < ( SELECT AVG(价格) FROM Books );
相关子查询示例:(查询Book表中大于该类图书价格平均值的图书信息)
SELECT*
FROM Books AS a
WHERE 价格 > (
SELECT AVG(价格)
FROM Books );
相关子查询执行过程:
(1)从外层查询中取出一个元组,将元组相关列的值传给内层查询。
(2)执行内层查询,得到子查询操作的值。
(3)外查询根据子查询返回的结果或结果集得到满足条件的行。
(4)然后外层查询取出下一个元组重复做步骤1-3,直到外层的元组全部处理完毕。
一般来说,能用子查询解决的问题也能用连接解决
- 按返回结果集分类:表子查询,行子查询,列子查询和标量子查询
- 标量子查询:返回1行1列一个值
SELECT num,name
FROM employee
WHERE d_id=(
select d_id
from department
where d_name='科技部' ) ;
可以指定一个标量表达式的任何地方,几乎都可以使用一个标量子查询,使用 = > < >= <= <> 这些比较标量结果的比较操作符。
- 行子查询:返回的结果集是 1 行 N 列
SELECT playerno
FROM players
WHERE (sex, town) = (
select sex, town
from players
where playerno = 100 ) ;
由于行子查询返回的结果集是 一行N列,因此不能直接使用 = > < >= <= <> 这些比较标量结果的比较操作符。
在行子查询中可以使用 IN、NOT IN等操作符。
- 列子查询:返回的结果集是 N 行 1列
SELECT playerno, name, town
FROM players
WHERE playerno in
( select playerno
from players
where sex = 'F' ) ;
由于列子查询返回的结果集是 N 行一列,因此不能直接使用 = > < >= <= <> 这些比较标量结果的比较操作符。
在列子查询中可以使用 IN、ANY、SOME、和ALL等操作符(与比较操作符联合使用)。
- 表子查询:返回的结果集是 N 行 N 列
SELECT playerno
FROM (
select playerno, sex
from players
where playerno < 10 ) AS players10
WHERE sex='M' ;
- 按照对返回结果的调用方法分类,where型子查询,from型子查询,exists型子查询以及select型子查询。
- where型子查询:(把内层查询结果当作外层查询的比较条件)
定义:where型的子查询就是把内层查询的结果当作外层查询的条件。 - from型子查询:(把内层的查询结果供外层再次查询)
定义:from子查询就是把子查询的结果(内存里的一张表)当作一张临时表,然后再对它进行处理。 - exists型子查询:(把外层查询结果拿到内层,看内层的查询是否成立)
- select型子查询:select子查询 (关键点:一个商品id,子查询只能返回一条数据,如果子查询返回多条数据则会出错)
- where型子查询:(把内层查询结果当作外层查询的比较条件)
SQL 中having 和where的区别:where子句用于筛选数据,不能用聚合函数;having子句可使用聚合函数,其专门用于配合group by。
WHERE:
SELECT Email
FROM(
select Email , count( Email ) as num
from Person
group by Email ) as statistic
WHERE num > 1
Having:
SELECT Email
FROM Person
GROUP BY Email
Having count( Email ) > 1
SQL中where子句中不能出现聚合函数的原因 (语法问题?)
LeetCode第176题Null表示空值(但还是一个值),而查询不到的结果Null表示没有值
IF函数与IFNULL函数的使用
Limit的使用
方法一:使用子查询和 LIMIT 子句
将不同的薪资按降序排序,然后使用 LIMIT 子句获得第二高的薪资。
SELECT DISTINCT Salary AS SecondHighestSalary
FROM Employee
ORDER BY Salary DESC
LIMIT OFFSET 1
然而,如果没有这样的第二最高工资,这个解决方案将被判断为 “错误答案”,因为本表可能只有一项记录。为了克服这个问题,我们可以将其作为临时表(Select Null 返回 Null)
SELECT (
select distinct Salary
from Employee
order by Salary desc
limit 1 offset 1 ) AS SecondHighestSalary
方法二:使用函数 IFNULL
SELECT IFNULL (
( select distinct Salary
from Employee
order by Salary desc
limit 1 offset 1 ) ,NULL) AS SecondHighestSalary
延伸: IF表达式:IF(expr1,expr2,expr3) ,如果 expr1 是TRUE(expr1 != 0 and expr1 != NULL),则 IF( )的返回值为expr2 ; 否则返回值则为 expr3。IF() 的返回值为数字值或字符串值,具体情况视其所在语境而定。
IFNULL表达式:IFNULL(expr1,expr2) , 如果expr1 不为 NULL,则 IFNULL() 的返回值为 expr1 ; 否则其返回值为 expr2。IFNULL()的返回值是数字或是字符串,具体情况取决于其所使用的语境。
注:要IF语句前要加上SELECT才能将其中的数值提取出来
limit 与offset 的区别:limit y 表示: 读取 y 条数据 ;limit x, y 表示: 跳过 x 条数据,读取 y 条数据; limit y offset x 表示: 跳过 x 条数据,读取 y 条数据。
LeetCode第177题SQL自定义函数的使用:
CREATE FUNCTION getNthHigherstSalary(N INT)RETURNS INT
BEGIN
SET N:=N-1
RETURN(
SELECT salary
FROM employee
ORDER BY salary DESC
LIMIT N,1 ) ;
END
注:要IF语句前要加上SELECT才能将其中的数值提取出来
标量值函数定义格式: 详见 SQL server 自定义函数FUNCTION的使用_蓝星部队的博客-CSDN博客_sql server 函数
DATE数据类型需要专门的时间处理函数例如DATEDIFF来处理
SQL的delete操作:
单表:DELETE FROM Person WHERE LastName = 'Wilson'
多表:
从数据表t1中把那些在数据表t2里有匹配的记录全删除掉:DELETE t1 FROM t1,t2 WHERE t1.id=t2.id
从数据表t1里在数据表t2里没有匹配的记录查找出来并删除掉:
DELETE t1 FROM t1 LEFT JOIN T2 ON t1.id=t2.id WHERE t2.id IS NULL
从两个表中找出相同记录的数据并把两个表中的数据都删除掉:
DELETE t1,t2 FROM t1 LEFT JOIN t2 ON t1.id=t2.id WHERE t1.id=25
Mysql DELETE 不能使用别名? 是我不会用! - 漠里 - 博客园
LeetCode第626题
这道题目实际上很简单:查询id和student,若id是偶数,减1;若id是奇数,加1;问题在于当总数为奇数时,最后一个id应保持不变,加1会导致空出一位。那么我们找到最后一位,让它保持不变就可以了。于是得到了下面的结果:
SELECT
IF( id % 2=0,
id-1,
if( id = (select count(distinct id) from seat ), id , id+1 ) )
AS id , student
FROM seat
ORDER BY id
LeetCode第627题 方法SQL CASE WHEN 知识点:CASE WHEN 用法 - 简书
延伸:Update 语句: Update 语句用于修改表中的数据。
UPDATE 表名称 SET 列名称 = 新值 WHERE 列名称 = 某值
Count ( ) 函数,可以放多个参数
SELECT round(
ifnull(
(select count( distinct requester_id , accepter_id) from request_ accepted) /
(select count(distinct sender_id ,send_to_id) from friend_ request)
,0)
,2) as accept_rate ;
Order by所依据的列可以自定义
Select 结束后才执行Order by ,Order by 的根据是指定的列,而本例后面跟的聚合函数值相当于一列。https://blog.csdn.net/u010002184/article/details/89601279
SELECT question_ id AS 'survey_ 1og'
FROM survey_ _1og
GROUP BY question_ id
ORDER BY COUNT( answer_ id ) / COUNT( IF ( action = 'show', 1, 0) ) DESC
LIMIT 1;
SELECT `Name`
FROM f
ORDER BY S_days/Grade DESC
Where ( )也可以放多个参数
Where ( a,b )in ( select c,d from …… )
SQL UNION 操作符
UNION 操作符用于合并两个或多个 SELECT 语句的结果集。
请注意,UNION 内部的 SELECT 语句必须拥有相同数量的列。列也必须拥有相似的数据类型。同时,每条 SELECT 语句中的列的顺序必须相同。
SQL UNION 语法
SELECT column_name(s) FROM table_name1
UNION
SELECT column_name(s) FROM table_name2
注释:默认地,UNION 操作符选取不同的值。如果允许重复的值,请使用 UNION ALL。
示例:https://www.w3school.com.cn/sql/sql_union.asp
此外,还能使用union来代替mysql没有的全连接
Any , in , some , all , exists , not in 等是子查询关键词
而max( ) , avg( ) , count( ) , min( ) , sum( ) , first( )等是聚合函数,配合group by使用
网友评论