Learn a little about associated queries, select seven clauses and subqueries every day

Association query

Seven results of relational query

(1) Inner connection

(2) Outer join: left outer join, right outer join, full outer join ( mysql uses union instead of full outer join )
insert image description here

Cartesian Product Phenomenon: When two tables are connected and queried, there are no restrictions. The final number of query results is the product of the number of records in the two tables.

  • How to avoid the Cartesian product phenomenon? Of course, add conditions to filter.
  • Thinking: Avoiding the Cartesian product phenomenon, will it reduce the number of record matches?
    No, the number of times is still the product of the number of records in the two tables, but only valid records are displayed.

About table aliases:

select e.ename,d.dname from emp e,dept d;

What are the benefits of table aliases?

  • First: high execution efficiency.
  • Second: good readability

Inner join: realize A∩B

Assuming that the A and B tables are connected, if the inner connection is used, all the records in the A table and the B table that can be matched are queried, which is the inner connection.
The two tables AB are not divided into primary and secondary tables, and the two tables are equal.

Format:

select 字段列表
from A表 inner join B表
on 关联条件
where 等其他子句;


select 字段列表
from A表 , B表
where 关联条件 and 等其他子句;

case analysis:

#查询有部门的员工和有员工的部门
#不使用内连接的写法
select * from t_employee emp,t_department dept where emp.did=dept.did;

#使用内连接,内连接和表的顺序无关,通过内连接查询的数据必须满足关联条件
select * from t_employee emp inner join t_department dept on emp.did=dept.did;
SELECT * FROM t_department dept INNER JOIN t_employee emp ON emp.did = dept.did;

#查询薪资高于20000的男员工的姓名和他所在的部门的名称
SELECT ename "员工的姓名",dname "部门名称"
FROM t_employee INNER JOIN t_department
ON t_employee.did = t_department.did
WHERE salary>20000 AND gender = '男'

Left outer join: realize A and A - A∩B

Outer join:
Assume that A and B tables are connected. If outer join is used, one of the two tables of AB is the main table and the other is the sub-table. The main query is the data in the main table, and the sub-table is incidentally queried as the sub-table. The data in the table does not match the data in the main table, and the sub-table automatically simulates NULL to match it.

The most important feature of the outer connection is that all the data in the main table can be queried unconditionally.

Format:

select 字段列表
from A表 left join B表
on 关联条件
where 从表关联字段 is null and 等其他子句;

case analysis:

#A的情况:
#查询所有员工的姓名和所在的部门   会以左边的表为主表,查询出所有的数据,哪怕不符合关联条件可以有为null的数据. 哪怕该员工没有部门
select ename,dname from t_employee emp left join t_department dept on emp.did=dept.did;

#A-A∩B的情况:
#查询所有没有部门的员工
select ename,dname from t_employee emp left join t_department dept
on emp.did=dept.did where emp.did is null;

Right outer join: realize B and BA∩B

Format:

select 字段列表
from A表 right join B表
on 关联条件
where 从表关联字段 is null and 等其他子句;

case analysis:

#查询所有部门,以及所有部门下的员工信息   会以右边的表为主表,查询出所有的数据,哪怕不符合关联条件.  哪怕该部门没有员工
select * from t_employee emp right join t_department dept on emp.did=dept.did;

#查询没有员工的部门
select * from t_employee emp right join t_department dept on emp.did=dept.did where emp.did is null;

Use union instead of full outer join: realize A∪B or A∪(BA∩B) or B∪(AA∩B) and A∪B - A∩B or (A - A∩B) ∪ (B - A∩B )

Format:

select 字段列表
from A表 left join B表
on 关联条件
where 从表关联字段 is null and 等其他子句

union

select 字段列表
from A表 right join B表
on 关联条件
where 从表关联字段 is null and 等其他子句

case analysis:

#查询所有的员工和部门
select * from t_employee emp left join t_department dept on emp.did=dept.did
union
select * from t_employee emp right join t_department dept on emp.did=dept.did;

select * from t_employee emp left join t_department dept on emp.did=dept.did
union
select * from t_employee emp right join t_department dept on emp.did=dept.did where emp.did is null;

#查询那些没有部门的员工和所有没有员工的部门
#没有部门的员工
SELECT *
FROM t_employee LEFT JOIN t_department
ON t_employee.did = t_department.did
WHERE t_employee.did IS NULL

UNION 

#所有没有员工的部门
SELECT *
FROM t_employee RIGHT JOIN t_department
ON t_employee.did = t_department.did
WHERE t_employee.did IS NULL

Special relational query: self-join

The tables of the two associated queries are the same table, which can be virtualized into two tables by taking an alias

Format:

select 字段列表
from 表名 别名1 inner/left/right join 表名 别名2
on 别名1.关联字段 = 别名2.关联字段
where 其他条件

case analysis:

#查询员工的编号,姓名,薪资和他领导的编号,姓名,薪资
#这些数据全部在员工表中
#把t_employee表,即当做员工表,又当做领导表
#领导表是虚拟的概念,我们可以通过取别名的方式虚拟
SELECT emp.eid "员工的编号",emp.ename "员工的姓名" ,emp.salary "员工的薪资",
	mgr.eid "领导的编号" ,mgr.ename "领导的姓名",mgr.salary "领导的薪资"
FROM t_employee emp INNER JOIN t_employee mgr
#t_employee emp:如果用emp.,表示的是员工表的
#t_employee mgr:如果用mgr.,表示的是领导表的
ON emp.mid = mgr.eid

#表的别名不要加"",给列取别名,可以用"",列的别名不使用""也可以,但是要避免包含空格等特殊符号。

The 7 major clauses of the select statement

7 major clause order

(1) from: Which tables to filter from
(2) on: When associating multi-table queries, remove the Cartesian product
(3) where: Conditions for filtering from tables
(4) group by: Grouping basis
(5) having: in Filter again in the statistical results
(6) order by: sorting
(7) limit: pagination
Clauses must be written in the order (1)-(7). Note: on is mainly followed by association conditions, where is followed by fields as conditions, and having is followed by grouping functions as conditions

case analysis:

#查询每个部门的男生的人数,并且显示人数超过5人的,按照人数降序排列,
#每页只能显示10条,我要第2页
SELECT did,COUNT(*) "人数"
FROM t_employee
WHERE gender = '男'
GROUP BY did
HAVING COUNT(*)>5
ORDER BY 人数 DESC
LIMIT 10,10
#测试on
SELECT * FROM t_employee ON eid > 10;  -- X
SELECT * FROM t_employee emp LEFT JOIN t_department dept ON emp.eid = 10;  -- √
#测试where
SELECT * FROM t_employee WHERE eid > 10; -- √
SELECT AVG(salary) FROM t_employee WHERE AVG(salary)>15000 GROUP BY did;  -- X

group by and grouping functions

(group by alone has no meaning and must be used in combination with grouping functions)
insert image description here

  • The data in the table can be divided into several groups using the GROUP BY clause
SELECT column, group_function(column)
FROM table
[WHERE	condition]
[GROUP BY	group_by_expression];

Clear: WHERE must be placed after FROM before GROUP BY

  • All columns in the SELECT list not included in the grouping function should be included in the GROUP BY clause
SELECT   department_id, AVG(salary)
FROM     employees
GROUP BY department_id ;
  • Columns included in the GROUP BY clause do not have to be included in the SELECT list
SELECT   AVG(salary)
FROM     employees
GROUP BY department_id ;
  • group by multiple columns
    insert image description here
SELECT   department_id dept_id, job_id, SUM(salary)
FROM     employees
GROUP BY department_id, job_id ;

having and grouping functions

insert image description here

SELECT   department_id, MAX(salary)
FROM     employees
GROUP BY department_id
HAVING   MAX(salary)>10000 ;

The difference between having and where?
(1) where is the condition to filter from the table, and having is to filter again in the statistical results, so the subsequent condition must be the field or grouping function that appears after select (2) "grouping/aggregation function" must not be
added after where, and Having can be followed by a grouping function

#测试having
SELECT * FROM t_employee HAVING eid > 10; -- √
SELECT AVG(salary) FROM t_employee WHERE did IS NOT NULL GROUP BY did HAVING AVG(salary) > 15000;
SELECT did,AVG(salary) FROM t_employee WHERE did IS NOT NULL GROUP BY did HAVING eid > 10; -- X
SELECT did,AVG(salary) FROM t_employee WHERE did IS NOT NULL GROUP BY did HAVING did > 1; -- √
SELECT did,AVG(salary) FROM t_employee WHERE did IS NOT NULL AND did > 1 GROUP BY did; -- √


#统计部门平均工资高于8000的部门和平均工资
SELECT   department_id, AVG(salary)
FROM     employees
WHERE    AVG(salary) > 8000 #错误
GROUP BY department_id;

insert image description here

#统计部门平均工资高于8000的部门和平均工资
SELECT   department_id, AVG(salary)
FROM     employees
GROUP BY department_id
HAVING   AVG(salary)>8000 ;

order by

order by:

  • Descending order: desc

  • Ascending order: use the default, or add asc

limit

limit index,pageSize
index:当前页的起始索引
pageSize:每页显示的条数
pageNum:当前页的页码
index = (pageNum-1)*pageSize
pageNum=1,pageSize=4limit 0,4
pageNum=4,pageSize=4limit 12,4
pageNum=8,pageSize=4limit 28,4
pageNum=4,pageSize=6limit 18,6
limit 4-->limit 0,4

subquery

The query nested in another query is divided into: where type, from type, and exists type according to different positions.Note: No matter where the subquery is, the subquery must be enclosed in ().

1. where type

Where-type subquery: use the data queried by a certain SQL statement as a SQL conditional query

  • 1. In the where type subquery, the query field can only have one column, otherwise: Operand should contain 1 column(s)
  • 2. In the where type subquery, if the SQL of the subquery returns multiple rows of data, you cannot use "=", but you can use in
  • 3. In the where type subquery, if the SQL of the subquery returns multiple rows of data, you cannot use ">", "<", ">=", "<=", but you can use all or any

    all(subquery result): greater than the maximum value
    any(subquery result): greater than the minimum value
    < all(subquery result): less than the minimum value
    < any(subquery result): less than the maximum value

#查询薪资最高的员工信息
SELECT eid,ename,MAX(salary) FROM t_employee 
WHERE salary = (SELECT MAX(salary) FROM t_employee);

#查询每个部门中最高薪资的员工信息
select *from t_employee where salary in(select max(salary) from t_employee where did is not null group by did);
#不加where is not null 会把did为空的分为一个新的组,即不需要显示没有部门的员工信息

#查询大于每个部门的平均薪资的员工信息
SELECT * FROM t_employee 
WHERE salary > ALL(SELECT AVG(salary) FROM t_employee WHERE did IS NOT NULL GROUP BY did);

#查询至少大于一个部门的平均薪资的员工信息
SELECT * FROM t_employee 
WHERE salary > ANY(SELECT AVG(salary) FROM t_employee WHERE did IS NOT NULL GROUP BY did);

2. from type

  • The result of a subquery is a result of multiple rows and multiple columns, similar to a table.

  • You must alias the subquery, that is, the name of the temporary table, and do not add "" and spaces to the alias of the table.

#查询每个部门的信息以及每个部门的最高薪资,最低薪资,平均薪资
SELECT dept.*,temp.maxSalary,temp.minSalary,temp.avgSalary
FROM t_department dept
LEFT JOIN 
(SELECT did,MAX(salary) maxSalary,MIN(salary) minSalary,AVG(salary) avgSalary FROM t_employee GROUP BY did) temp
ON dept.did = temp.did;

#查询每个部门的编号,名称,平均工资
select 部门编号, 部门名称, 平均工资
from 部门表 inner join (select 部门编号,avg(薪资) from 员工表  group by 部门编号) temp
on 部门表.部门编号 = temp.部门编号

3. exists type

查询那些有员工的部门
select 部门编号, 部门名称 from 部门表
where exists (select * from 员工表  where 部门表.部门编号 = 员工表.部门编号);

Guess you like

Origin blog.csdn.net/qq_52370789/article/details/129559069