参考资料

廖雪峰sql教程
sqlzoo在线教程:sqlzoo/参考答案
更多练习题:

概览

1、sql对关键字不区分大小写
2、别名

  1. -- as 作为别名
  2. FROM name as student_name from student;
  3. -- as 也可以省掉
  4. FROM name student_name from student;
  5. -- 表别名
  6. SELECT e.id,e.name FROM Employee e;

3、语法用法简单记录:

  1. 条件&限制:where , order by, case...when...
  2. 分组:group by ...having,
  3. 模糊查询:like关键字与通配符
  4. 子查询:unionall
  5. 表连接查询:joinleft (outer) join right (outer) joincross join

—case when

  1. [case ... when (condition)
  2. then xxx
  3. else xxx
  4. end]
  5. select id,
  6. #对字段a进行赋值,如果当前满足when的条件 则a为1 否则a为0
  7. case when array_contains(id_courses, courses[0]) then 1 else 0 end as a,
  8. case when array_contains(id_courses, courses[1]) then 1 else 0 end as b,
  9. case when array_contains(id_courses, courses[2]) then 1 else 0 end as c,
  10. case when array_contains(id_courses, courses[3]) then 1 else 0 end as d,
  11. case when array_contains(id_courses, courses[4]) then 1 else 0 end as e,
  12. case when array_contains(id_courses, courses[5]) then 1 else 0 end as f
  13. from id_courses;

查询

查询可有:基本查询、条件查询、投影查询、聚合查询、多表查询、连接查询;
语法是:

  1. select [all | distinct] select_expr, select_expr, ...
  2. from table_reference
  3. [where where_condition]
  4. [group by col_list]
  5. [order by col_list]
  6. [cluster by col_list
  7. | [distribute by col_list] [sort by col_list]
  8. ]
  9. [limit [offset,] rows]

大致思路是从xx表里对表格的数据进行筛选、缩减、或者扩充连接,形成新的“表”,再在新的表上select我们关心的列出来形成结果表。
以下面两个表(部门表、员工表)为例子说明常见的查询:

基本查询
SELECT * FROM Employee; 展示员工表所有列

==

条件查询

SELECT * FROM students WHERE sal >= 80;
条件查询灵魂在于条件判断表达式:
语法是where 条件; 多条条件通过and、or关联;表达式:=、>、<、<>、like等;
where .. between … and …; is null / is not null ; in/not in;exp: t.name in (‘haha’,’hehe’);

p.s.
having 针对分组数据进行筛选 Group By … Having ;exp:select e.deptno,avg(e.sal) avgsal from emp e group by e.deptno having avgsal>2000;

like 与 rlike
(1)like的内容 不是正则 ,而是通配符。
(2)rlike的内容可以是正则。

like即对应模糊查询,类似于开启字符串匹配;

通配符 描述
% 替代一个或多个字符
_ 仅替代一个字符
[charlist] 字符列中的任何单一字符
[^charlist]或者[!charlist] 不在字符列中的任何单一字符
  1. u_name为“张三”,“张猫三”、“三脚猫”,“唐三藏”等等有“三”的记录全找出来。
  2. SELECT * FROM [user] WHERE u_name LIKE '%三%'
  3. 既有“三”又有“猫”的记录
  4. SELECT * FROM [user] WHERE u_name LIKE '%三%' AND u_name LIKE '%猫%'
  5. SELECT * FROM [user] WHERE u_name LIKE '_三_'
  6. 只找出“唐三藏”这样u_name为三个字且中间一个字是“三”的;
  7. SELECT * FROM [user] WHERE u_name LIKE '[张李王]三'
  8. 将找出“张三”、“李三”、“王三”(而不是“张李王三”);
  9. SELECT * FROM [user] WHERE u_name LIKE '[^张李王]三'
  10. 将找出不姓“张”、“李”、“王”的“赵三”、“孙三”等;

image.png

concat函数 ,连接多个字符串,好处在于 concat里面的数是变量,变量可以是select 的字段 也可以是 通配符

image.png

image.png

==
投影查询
如果我们只希望返回某些列的数据,而不是所有列的数据,我们可以用SELECT 列1, 列2, 列3 FROM ...,让结果集仅包含指定列。这种操作称为投影查询。
SELECT id, score, name FROM students;

==

聚合查询

如果我们要统计一张表的数据量,例如,想查询students表一共有多少条记录,难道必须用SELECT * FROM students查出来然后再数一数有多少行吗?
对于统计总数、平均数这类计算,SQL提供了专门的聚合函数,使用聚合函数进行查询,就是聚合查询
SELECT COUNT() FROM students; `COUNT()`表示查询所有列的行数; count(*)=count(id)
除count外还提供 sum、avg、min、max等函数

聚合查询还有个重要的知识点—分组:
如果我们要统计一班的学生数量,我们知道,可以用SELECT COUNT(*) num FROM students WHERE class_id = 1;。如果要继续统计二班、三班的学生数量,难道必须不断修改WHERE条件来执行SELECT语句吗?
对于聚合查询,SQL还提供了“分组聚合”的功能

  1. SELECT * FROM students;

image.png

按照班级划分,每班多少人

  1. SELECT class_id,count(class_id) FROM students group by class_id;

image.png

按照性别划分,统计男女各有多少人

  1. SELECT gender,count(gender) FROM students group by gender;

image.png

分组group by的作用是对某个属性进行“桶计数的感觉”,找出该属性下有多少种类,显示出来,然后一般搭配聚合函数算出个数;
所以即使当我们 select * group by class_id; 展示的列也仅有 class_id;

image.png

分组更强大的地方在于,我们使用多列进行分组;
比如我们想统计各班男女人数

  1. SELECT class_id, gender, COUNT(*) FROM students GROUP BY class_id, gender;

image.png

能展示的列还是遵循group by 什么属性就一定可以显示什么属性,同时再在显示的属性上进行聚合计算即可;

==

连接查询

连接查询是另一种类型的多表查询。连接查询对多个表进行JOIN运算,简单地说,就是先确定一个主表作为结果集,然后,把其他表的行有选择性地“连接”在主表结果集上。

从语法角度join分为

join 区别
(inner) join 内连接就是关联的两张或多张表中,根据关联条件,显示所有匹配的记录,匹配不上的,不显示
只连接双方都存在的情况
left (outer) join 显示左表的所有项,右表没有匹配的项,则以null显示
right (outer) join 显示右表的所有项,左表没有匹配的项,则以null显示
full (outer) join 显示所有匹配和不匹配的项,左右两张表没有匹配的,都以null显示

一图胜千言:
image.png

一般join是为了表的信息扩充,比如学生表(studenid,name)和成绩表(studenid,score)
他们通过studentid相连接,可以得到xxname的学生的考试成绩是多少;此类为不同表之间的连接

  1. select * from student S left join score C
  2. where S.studentid = C.studentid

此外也可以 自身连接,即自连接;

以外还有cross join用于生成两张表的笛卡尔集。
1、返回的记录数为两个表的记录数乘积。比如,A表有n条记录,B表有m条记录,则返回n*m条记录。
2、将A表的所有行分别与B表的所有行进行连接。

其实所有的连接都是从 cross join演化而来的;但是目前用的比较少这里不再细究;

子查询

对于支持子查询的数据库,Hibernate 支持在查询中使用子查询。一个子查询必须被圆括号包围起来(经常是 SQL 聚集函数的圆括号)。甚至相互关联的子查询(引用到外部查询中的别名的子查询)也是允许的。
大白话就是在sql形成的暂时表里再精简查询,表现为嵌套的视觉体现

如果子查询只有一个结果:

  1. select * from Cat as fatcat
  2. where fatcat.weight >
  3. (
  4. select avg(cat.weight) from DomesticCat cat
  5. )

如果是多个,使用in关键字
列出与巴西、墨西哥相同洲的每个国家的名字和洲

  1. SELECT name, continent FROM world
  2. WHERE continent IN
  3. (SELECT continent
  4. FROM world WHERE name='Brazil'
  5. OR name='Mexico')

除了使用 > , < , >=,<=等比较符,还可以使用all、any来筛选

找出哪个国家的人口是高于欧洲每个国家的人口

  1. SELECT name FROM world
  2. WHERE population > ALL
  3. (SELECT population FROM world
  4. WHERE continent='Europe')

union

用来合并多个select的查询结果,需要保证select中字段须一致

  1. select_statement UNION ALL select_statement UNION ALL select_statement