SQL 2020-03-15(未经允许,禁止转载)

几个不错的在线学习+练习网站

SQL动物园https://sqlzoo.net/wiki/
SQL机器人https://sqlbolt.com/
学SQL(SQL机器人的中文版,recommended)http://xuesql.cn/

比较丰富但基础的练习题可以看,适合实践巩固:
https://www.w3resource.com/sql-exercises/
另外,leetcode也有SQL的练习题


前情提要

关系型数据库背后是所谓的“关系代数”
“关系代数”的基本操作是很简单的,包括交、并、差,以及笛卡尔积,sql语句最后也是被翻译成这些基操而已
表之间关系明显,对数据的一致性准确性要求很高(也就是事务支持)

知识小结,以MySQL为例:

1.SQL基础

SQL是一种statement声明式语言,它仅仅是声明了一个你想从原始数据中获得某种样式的结果范例,而不像编程那样需要明确指示计算机如何操作

基本语法

# 创建数据库
CREATE DATABASE <数据库名>;
CREATE SCHEMA <数据库名>;
说明:CREATE SCHEMA is a synonym for CREATE DATABASE

# 删除数据库
DROP DATABASE <数据库名>;

# 切换数据库
USE <数据库名>;

# 创建基本表
CREATE TABLE <表名>
(列名称1 数据类型,
列名称2 数据类型,
列名称3 数据类型);

# 删除基本表
DROP TABLE <表名>;

# 增
INSERT INTO <表名> (COL1, COL2, ...) VALUES (V1, V2, ...);

# 删
DELETE FROM <表名> WHERE ...;

# 改
UPDATE <表名> SET COL1=V1, COL2=V2 WHERE ...;

# 查
SELECT COL1, COL2, ... FROM <表名> WHERE ...;

说明:MySQL默认打开safe update mode当safe update mode打开时,如果需要改动且存在WHERE子句,那么WHERE的筛选必须基于主键。即DELETE和UPDATE的WHERE条件必须基于主键,否则报错Error Code: 1175. You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column.
关闭MySQL的safe update mode,可以通过命令SET SQL_SAFE_UPDATES = 0;

2.SQL进阶

DISTINCT
返回目标字段中不重复的值,只能在select语句中使用
SELECT DISTINCT col1, col2, ... FROM <表名> [WHERE conditions];

  • DISTINCT多对单列使用;对多列操作时,表示选取多列都不重复的数据,即多列拼接成一条记录,返回不重复的记录
  • DISTINCT返回的结果中不会过滤NULL,也就是可以包含NULL值

In most cases, a DISTINCT clause can be considered as a special case of GROUP BY. For example, the following two queries are equivalent:

SELECT DISTINCT c1, c2, c3 FROM t1
WHERE c1 > const;

SELECT c1, c2, c3 FROM t1
WHERE c1 > const GROUP BY c1, c2, c3;

Due to this equivalence, the optimizations applicable to GROUP BY queries can be also applied to queries with a DISTINCT clause. Thus, for more details on the optimization possibilities for DISTINCT queries

JOIN ON
JOIN ON = 按笛卡尔积【A×B={(x,y)|x∈A∧y∈B}】拼接多张表. The SQL JOIN clause is used whenever we have to select data from 2 or more tables.
JOIN分为INNER JOIN / LEFT JOIN / RIGHT JOIN / FULL JOIN
直接上表说明

person表

name age gender
Alice 23 0
Bob 24 1

job表

name job
Alice Engineer
Alice Officer
Clark Manager

下面开始JOIN

  • SELECT * FROM person INNER JOIN job ON person.name = job.name
person.name age gender job.name job
Alice 23 0 Alice Engineer
Alice 23 0 Alice Officer

INNER JOIN:person表与job表满足ON条件的记录进行笛卡尔乘积

  • SELECT * FROM person LEFT JOIN job ON person.name = job.name
person.name age gender job.name job
Alice 23 0 Alice Engineer
Alice 23 0 Alice Officer
Bob 24 1 NULL NULL

LEFT JOIN: 即使右表中没有匹配,也从左表返回所有的行

  • SELECT * FROM person RIGHT JOIN job ON person.name = job.name
person.name age gender job.name job
Alice 23 0 Alice Engineer
Alice 23 0 Alice Officer
NULL NULL NULL Clark Manager

RIGHT JOIN: 即使左表中没有匹配,也从右表返回所有的行

  • SELECT * FROM person FULL JOIN job ON person.name = job.name
person.name age gender job.name job
Alice 23 0 Alice Engineer
Alice 23 0 Alice Officer
Bob 24 1 NULL NULL
NULL NULL NULL Clark Manager

FULL JOIN: 返回两表的全部记录,不满足ON条件的就置NULL

SQL的执行顺序8步走——从FROM来,到ORDER BY去
在执行过程中,每个步骤都会为下一个步骤生成一个虚拟表,这个虚拟表将作为下一个执行步骤的输入

FROM——加载原始表格
WHERE——通过where筛选器挑出原始表中满足条件的子表,但无法与聚合函数一起使用;同时,不可使用select中的别名
GROUP BY——分组。如果应用了group by,那么只为每个组保留一行记录
HAVING——筛选分组。HAVING的出现就是为了解决WHERE无法与聚合函数一起使用的不足,几乎都与GROUP BY连用以实现记录分组+筛选出目标组。如先按国家分组,然后对每个国家计算gdp总量,筛选大于1000的:GROUP BY country HAVING SUM(gdp) > 1000
--上面4步负责获取满足各种筛选条件后的记录,更重要
--下面4步负责处理显示给人看的结果
SELECT——挑拣需要的列
DISTINCT——显示去重
UNION——合并两个或多个 SELECT 语句的结果集。注意是上下合并而不是左右拼接
ORDER BY——调整显示顺序

SQL执行顺序(来源网络)

sql执行流程图(来源网络)

根据SQL的执行顺序,字段/表达式的别名在WHERE子句和GROUP BY子句都不能使用,因为此时别名还没有生效;而在order by中不仅可以使用别名,还可以直接使用字段的下标来进行排序,如:order by 1 desc

The COALESCE() function returns the first non-null value in a list.

SELECT
  coalesce(host_agent.agent_version, 'offline') as version,
  count(*) as count
FROM
  host
  left join host_agent on host.id = host_agent.host_id
  and host_agent.agent_name = "test_agent"
group by host_agent.agent_version 

host机器表,host_agent 机器上安装的agent 表
一个机器上安装了若干agent
目标是查询所有机器上安装的test_agent的版本分布情况,对于没有安装test_agent的以offline记录。例如

version count
1.0 9999
offline 999
... ...

那么,对于没有安装test_agent的host,join后的右表字段全是null,也就是说host_agent.agent_version是null,这部分要以offline来显示。用到The COALESCE() function, which returns the first non-null value in a list.

条件判断CASE WHEN THEN ELSE END
CASE WHEN就是编程中的if else, 在实际工作环境中,CASE WHEN的使用频率和SELECT差不多

case
when condition1 then result1
when condition2 then result2
...
else default
end

condition是待求值的表达式,如果它的返回值是真,则返回对应result
例如:
SELECT
CASE
WHEN salary <= 500 THEN '1'
WHEN salary > 500 AND salary <= 600 THEN '2'
WHEN salary > 600 AND salary <= 800 THEN '3'
WHEN salary > 800 AND salary <= 1000 THEN '4'
ELSE NULL END salary_class, -- 别名命名
COUNT(*)
FROM Table_A;

分组排序row_number() over() or rank() over()

  • row_number() over(partition by col1 order by col2)
    很好理解,字面意思,按col1分组,组内按col2排序,返回行号
    row_number() over()
  • rank() over(partition by col1 order by col2)
    也很好理解,字面意思,按col1分组,组内按col2排序,返回排名
    rank() over()

    行号是绝对顺序的,而排名是可以并列的

查看mysql变量

show variables [like "%variable_name%"]
show variables like "%innodb_deadlock_detect%"

查看mysql当前实时状态

show status [like "%status_name%"]

ddl

ALTER TABLE table_name ALTER COLUMN column_name SET DEFAULT 'literal';

ALTER TABLE
  table_name
ADD
  COLUMN column_name VARCHAR(50) NOT NULL DEFAULT('') COMMENT 'xxx',
ADD
  INDEX (column_name)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。