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)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,588评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,456评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,146评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,387评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,481评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,510评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,522评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,296评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,745评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,039评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,202评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,901评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,538评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,165评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,415评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,081评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,085评论 2 352