What is SQL?

  • Structured Query Language(结构化查询语言)

  • SQL是数据查询语言,数据库(Oracle、MySql、SQLite、Microsoft SQL Server)等是存储与管理数据的软件

关系型数据库(Relational databases)

  • 数据库由若干张表(Table)组成,Table也是由行和列组成

  • 一个Table存储一个类别的数据,每一行是一条数据,每一列是这种数据的一种属性

  •  Table就像一个二维的表格,是有限固定的,行(rows)是无限不固定的

SELECT 查询

  • SELECT语句,通常又称为查询(queries),SELECT可以用来从数据库中取出数据

取出表中所有数据的一个或某几个属性列

Select 查询某些属性列(specific columns)的语法

SELECT column(列名) , another column , ... FROM mytable(表名);

  • 查询的结果是一个二维的表格,由行(rows)和列(columns)组成

取出所有列的数据

  • 可以把所有列名写上,不过更简单的方式用星号 (*) 来代表所有列

SELECT * FROM mytable(表名) ;

条件查询

SELECT查询的 WHERE 子句

SELECT column, another_column, …
FROM mytable
WHERE condition
    AND/OR another_condition
    AND/OR …;

数字类型属性筛选

Operator(关键字)

Condition(意思)

SQL Example(例子)

=, !=, < <=, >, >=

Standard numerical operators 基础的 大于,等于等比较

col_name != 4

BETWEEN … AND …

Number is within range of two values (inclusive) 在两个数之间

col_name BETWEEN 1.5 AND 10.5

NOT BETWEEN … AND …

Number is not within range of two values (inclusive) 不在两个数之间

col_name NOT BETWEEN 1 AND 10

IN (…)

Number exists in a list 在一个列表

col_name IN (2, 4, 6)

NOT IN (…)

Number does not exist in a list 不在一个列表

col_name NOT IN (1, 3, 5)

虽然之前我们的SQL 关键字如 SELECTWHEREAND,OR 都是大写的,但SQL其实是兼容写成 select,where小写的

大写这些关键字有助于我们把 关键字 和 你的表名,列名区分开,让 SQL更容易理解。

字符串类型属性筛选

Operator(操作符)

Condition(解释)

Example(例子)

=

Case sensitive exact string comparison (notice the single equals)完全等于

col_name = "abc"

!= or <>

Case sensitive exact string inequality comparison 不等于

col_name != "abcd"

LIKE

Case insensitive exact string comparison 没有用通配符等价于 =

col_name LIKE "ABC"

NOT LIKE

Case insensitive exact string inequality comparison 没有用通配符等价于 !=

col_name NOT LIKE "ABCD"

%

Used anywhere in a string to match a sequence of zero or more characters (only with LIKE or NOT LIKE) 通配符,代表匹配0个以上的字符

col_name LIKE "%AT%"
(matches "AT", "ATTIC", "CAT" or even "BATS") "%AT%" 代表AT 前后可以有任意字符

_

Used anywhere in a string to match a single character (only with LIKE or NOT LIKE) 和% 相似,代表1个字符

col_name LIKE "AN_"
(matches "AND", but not "AN")

IN (…)

String exists in a list 在列表

col_name IN ("A", "B", "C")

NOT IN (…)

String does not exist in a list 不在列表

col_name NOT IN ("D", "E", "F")

  • 在字符串表达式中的字符串需要用引号 " 包含,如果不用引号,SQL会认为是一个属性列的名字

查询结果Filtering过滤 和 sorting排序

 DISTINCT 关键字

  • 指定某个或某些属性列唯一返回

选取出唯一的结果的语法
SELECT DISTINCT column, another_column, …
FROM mytable
WHERE condition(s);
  • 因为 DISTINCT 语法会直接删除重复的行, 还有 GROUP BY 语句, GROUP BY 也会返回唯一的行,不过可以对具有相同的 属性值的行做一些统计计算,比如:求和.

结果排序 (Ordering results)

结果排序(ordered results)
SELECT column, another_column, …
FROM mytable
WHERE condition(s)
ORDER BY column ASC/DESC;
  • ASC升序 或 DESC 降序

通过Limit选取部分结果

  • LIMIT 和 OFFSET 子句通常和ORDER BY 语句一起使用,当我们对整个结果集排序之后,可以 LIMIT来指定只返回多少行结果 ,用 OFFSET来指定从哪一行开始返回。

limited查询
SELECT column, another_column, …
FROM mytable
WHERE condition(s)
ORDER BY column ASC/DESC
LIMIT num_limit OFFSET num_offset;

用JOINs进行多表联合查询

数据库范式(normalization)

  • 数据库范式是数据表设计的规范,在范式规范下,数据库里每个表存储的重复数据降到最少(这有助于数据的一致性维护),同时在数据库范式下,表和表之间不再有很强的数据耦合,可以独立的增长

用JOINs进行多表联合查询

主键(primary key)

  • 一般关系数据表中,都会有一个属性列设置为 主键(primary key)。主键是唯一标识一条数据的,不会重复(想象你的身份证号码)。一个最常见的主键就是auto-incrementing integer(自增ID,每写入一行数据ID+1)当然字符串,hash值等只要是每条数据是唯一的也可以设为主键

  • 借助主键(primary key)(其他唯一性的属性也可以),我们可以把两个表中具有相同 主键ID的数据连接起来

 INNER JOIN

用INNER JOIN 连接表的语法
SELECT column, another_table_column, …
FROM mytable (主表)
INNER JOIN another_table (要连接的表)
    ON mytable.id = another_table.id 
WHERE condition(s)
ORDER BY column, … ASC/DESC
LIMIT num_limit OFFSET num_offset;

外连接(OUTER JOINs)

LEFT JOIN,RIGHT JOIN 和 FULL JOIN

用LEFT/RIGHT/FULL JOINs 做多表查询
SELECT column, another_column, …
FROM mytable
INNER/LEFT/RIGHT/FULL JOIN another_table
    ON mytable.id = another_table.matching_id
WHERE condition(s)
ORDER BY column, … ASC/DESC
LIMIT num_limit OFFSET num_offset;
  • 在表A 连接 B, LEFT JOIN保留A的所有行,不管有没有能匹配上B 反过来 RIGHT JOIN则保留所有B里的行。最后FULL JOIN 不管有没有匹配上,同时保留A和B里的所有行

  • 将两个表数据1-1连接,保留A或B的原有行,如果某一行在另一个表不存在,会用 NULL来填充结果数据

  • 在用这三个JOIN时,需要单独处理 NULL

特殊关键字 NULLs

  • outer-joining 多表连接,A和B有数据差异时,必须用 NULL 来填充。这种情况,可以用IS NULL和 IS NOT NULL 来选在某个字段是否等于 NULL.

在查询条件中处理 NULL
SELECT column, another_column, …
FROM mytable
WHERE column IS/IS NOT NULL
AND/OR another_condition
AND/OR …;

在查询中使用表达式

  • 在SQL中可以用col_name(属性名)的地方,都可以用表达式 来指定对属性进行一定的计算或处理

SELECT  particle_speed / 2.0 AS half_particle_speed (对结果做了一个除2)
FROM physics_data
WHERE ABS(particle_position) * 10.0 >500
            (条件要求这个属性绝对值乘以10大于500);
  • 每一种数据库(mysql,sqlserver等)都有自己的一套函数,包含常用的数字,字符串,时间等处理过程.具体需要参看相关文档

  • SQL提供了AS关键字, 来给表达式取一个别名

AS使用别名
SELECT col_expression AS expr_description, …
FROM mytable;

在查询中进行统计

对全部结果数据做统计
SELECT AGG_FUNC(column_or_expression) AS aggregate_description, …
FROM mytable
WHERE constraint_expression;

Function

Description

COUNT(*)COUNT(column)

计数!COUNT(*) 统计数据行数,COUNT(column) 统计column非NULL的行数.

MIN(column)

找column最小的一行.

MAX(column)

找column最大的一行.

AVG(column)

对column所有行取平均值.

SUM(column)

对column所有行求和.

Docs: MySQLPostgresSQLiteMicrosoft SQL Server

分组统计

  • GROUP BY 数据分组语法可以按某个col_name对数据进行分组,如:GROUP BY Year指对数据按年份分组, 相同年份的分到一个组里。如果把统计函数和GROUP BY结合,那统计结果就是对分组内的数据统计了

用分组的方式统计
SELECT AGG_FUNC(column_or_expression) AS aggregate_description, …
FROM mytable
WHERE constraint_expression
GROUP BY column;

HAVING语法

  • 在 GROUP BY 分组语法中,我们知道数据库是先对数据做WHERE,然后对结果做分组,如果我们要对分组完的数据再筛选出几条如何办?

  • 一个不常用的语法 HAVING 语法将用来解决这个问题,它可以对分组之后的数据再做SELECT筛选

用HAVING进行筛选
SELECT group_by_column, AGG_FUNC(column_expression) AS aggregate_result_alias, …
FROM mytable
WHERE condition
GROUP BY column
HAVING group_condition;

查询执行顺序

这才是完整的SELECT查询
SELECT DISTINCT column, AGG_FUNC(column_or_expression), …
FROM mytable
    JOIN another_table
      ON mytable.column = another_table.column
    WHERE constraint_expression
    GROUP BY column
    HAVING constraint_expression
    ORDER BY column ASC/DESC
    LIMIT count OFFSET COUNT;

FROM 和 JOINs

FROM 或 JOIN会第一个执行,确定一个整体的数据范围. 如果要JOIN不同表,可能会生成一个临时Table来用于 下面的过程。总之第一步可以简单理解为确定一个数据源表(含临时表)

WHERE

我们确定了数据来源 WHERE 语句就将在这个数据源中按要求进行数据筛选,并丢弃不符合要求的数据行,所有的筛选col属性 只能来自FROM圈定的表. AS别名还不能在这个阶段使用,因为可能别名是一个还没执行的表达式

GROUP BY

如果你用了 GROUP BY 分组,那GROUP BY 将对之前的数据进行分组,统计等,并将是结果集缩小为分组数.这意味着 其他的数据在分组后丢弃.

HAVING

如果你用了 GROUP BY 分组, HAVING 会在分组完成后对结果集再次筛选。AS别名也不能在这个阶段使用.

SELECT

确定结果之后,SELECT用来对结果col简单筛选或计算,决定输出什么数据.

DISTINCT

如果数据行有重复DISTINCT 将负责排重.

SELECT Title, (SELECT MAX(Domestic_sales+International_sales) 
FROM Boxoffice) - SUM(Domestic_sales+International_sales) 
AS Diff FROM Movies INNER JOIN Boxoffice 
ON Movies.ID = Boxoffice.Movie_id 
GROUP BY Title;