Table of Contents

Lucas Wu

用于数据科学的SQL

如今在数据科学中使用SQL查询数据是常见的操作,而大部分以表格(行和列)展示数据的数据格式,几乎都支持使用SQL进行查询,比如Dataframe、Excel。

同时通过Jupyter Notebook提供的Magic Statements和IPython_SQL,能够让SQL和Python进行非常方便的结合。

SQL

SQL全称为Structured Query Language 结构化查询语言,是基于Edgar F. Codd在1970年提出的关系模型理论,该模型引入了表(表格形式的数据结构)来表示数据以及其关系的概念,所以可以理解为最初的定位是用于操作和查询关系型数据库。

SQL 于 1986 年被 ANSI(美国国家标准学会)采纳,并于 1987 年被 ISO(国际标准化组织)采纳为关系型数据库的标准语言,所以目前制定标准的主要由ANSI和ISO两个组织。

SQL是一个标准,也是一个总称,SQL的定义了两个核心部分,第一个是标准的查询语句和标准的数据类型。

除了上述的这些子集,还有一些扩展的高级功能的子集,比如对非结构化数据的支持,使得SQL能够支持NoSQL、NewSQL以及大数据系统应用。

查询语句

查询语句主要是围绕着DDL、DML、DCL以及TCL几个核心的子集开展,而常见的SELCT、CREATE都是属于这些子集,核心子集每个数据库(DBMS)都是支持的,但是每个数据库针对于SQL的扩展都会都会有一些差异,所以如果考虑到迁移性,应该尽可能使用标准的核心SQL语句。

DDL(Data Definition Language)

DDL(数据定义语言),理解为数据库的地基,负责定义和修改数据库结构和对象(如表、视图和索引等),典型的语句有CREATE、ALTER和DROP等。

DML(Data Manipulation Language)

DML(数据操作语言),作用于操作数据库的数据,对数据库中的数据进行查询、插入、更新和删除等操作,典型的语句有 Select查询数据、 Insert插入数据、Update更新修改数据、 Delete删除数据等。

DQL(Data Query Language)是专门用于查询的子集,但是是由DML下的子集,所以DML包含查询。

DCL(Data Control Language)

DCL(数据控制语言),作用于控制用户权限,管理数据库对象的访问权限,典型的语句有Grant和Revoke等。

TCL(Transaction Control Language)

TCL(事物控制语言)是SQL子集,作用于管理事物,确保数据库操作的完整性,典型的语句有Commit、Rollback和Savepoint等。

数据类型

SQL除了操作查询数据的语句部分,还有定义了数据的类型,比如数值、字符串、日期、布尔值等,大部分都是比较好理解的,但日期则可以根据需求不同采用不同的日期类型,SQL定义了DATE、TIME和TIMESTAMP类型,主要差异在于:

  1. DATE:DATE类型有8位数,分别为YYYYMMDD。
  2. TIME:TIME类型有6位数,分别为HHMMSS。
  3. TIMESTAMP:TIMESTAMP有20位数,分别为YYYYXXDDHHMMSSZZZZZZ,其中XX代表月份,ZZZZZZ代表微秒。

一些记录

大部分SQL可以很容易查询到用法,但是部分查询在性能和实现则有一定的区别,同时也有存在多种解决方式。

Primary Key

数据库中主键有如下几个功能:

  1. 唯一性:设置为主键的属性(数据库中被映射为了列),是唯一值,能够避免数据重复。
  2. 一致性和完整性:主键确保表每一行都有一个唯一的标识符,这对于维护数据的一致性非常重要。
  3. 关联性:在关系型数据库中,主键用于建立表与表之间的关系(通过外键引用)。
  4. 加速:数据库在创建主键的时候,会为主键创建索引,使得通过主键查询会非常快。

ER模型和ERD图

Entity-Relationship Model(ER模型)

ER模型是用于设计实体关系模型的基础理论,关注实体(比如人)、实体的属性(比如人的头发、身高、体重、肤色等)以及相互之间的关联,ER模型的好处是可以针对字段进行规划关联、字段类型、主键以及多对一还是一对多等关系,同时设计完成后可以自动化生成sql进行自动建立数据库结构。

Entity Relationship Diagram(ERD图)

而ERD则是ER的一种图的实现,基于ER理论通过ERD进行设计实体关系图,会更加直观。

优势

如果只是画图,很多都可以画,但是ER模型和ERD都是专用数据库设计的,所以有很多其它画图工具达不到的功能,比如自动根据ERD图生成SQL脚本。

字符串查询和范围查询

SQL使用字符串进行查询,可以只给出部分关键词进行模糊查询,其中有%代表通配符(即匹配任何事情)。

select * from tablename where name like 'R%'

范围查询可以使用between和in关键词,比如查询2000-2010年之间的数据,使用比较运算符的大于等于和小于等于进行查询:

select * from tablename where RealseYear >= 2000 AND RealseYear <= 2010;

而上面的方式,同样使用比较运算符between和and等替:

select * from tablename where RealseYear BETWEEN 2000 and 2010;

再比如检查是不是等于某些值:

select * from tablename where Country = 'UK' OR Country = 'US';

这样给定几个值的查询可以使用in关键词,然后给定一个元组:

select * from tablename where Country in ('UK','US');

排序

SQL的排序使用语法:

SELECT * FROM TABLE ORDER BY COLUMN

指定排序列是一种方式,也可以给数值选定列排序,比如选择返回的数据集中的第二列进行排序:

SELECT * FROM TABLE ORDER BY 2

分组

SQL中使用GROUP BY关键词对结果进行分组,GROUP BY常与 聚合函数(如MAX、 MIN、COUNT、SUM)一起使用,对每组数据进行汇总计算,同时还可以使用HAVING关键词对分组结果进行过滤筛选。

GROUP BY

SQL中使用GROUP BY关键词对结果进行分组,将具有相同值的行归为一组。

SELECT column1, column2 FROM table_name GROUP BY column1, column2;

比如:

| product | category | quantity |

|---------|----------|----------|

| apple  | fruit  | 10    |

| banana | fruit  | 20    |

| carrot | vegetable| 15    |

| apple  | fruit  | 5    |

然后分组进行计算:

SELECT category, SUM(quantity) AS total_quantity

FROM sales

GROUP BY category;

结果为:

| category  | total_quantity |

|------------|----------------|

| fruit   | 15       |

HAVING

HAVING关键词用于筛选分组后的结果,与where不同的是,where会在分组前对原始数据进行筛选,而HAVING则是分组后的数据筛选,比如:

SELECT category, SUM(quantity) AS total_quantity

FROM sales

GROUP BY category

HAVING total_quantity > 20;

子查询

子查询与嵌套查询是一个意思,都是指SQL中将一个查询语句嵌套在另外一个查询语句中作为条件或者数据源

子查询根据使用不同,可以返回单个值或者多个值来配合外部的查询。

一般在SQL语句中,子查询用括号包裹,并且存在于SELECT中作为列,WHERE作为条件,FROM或JOIN作为表。

SELECT

子查询返回多个或者单个值,作为外部查询的列值。

SELECT *, ( SELECT name FROM table2 ) as name FROM table1;

WHERE

子查询返回一个或者多个值,用于过滤外部查询的结果。

SELECT * FROM table1 WHERE age > ( SELECT avg(age) FROM table2 where age >= 18) ;

返回子查询中的结果,也就是name和age。

FROM或JOIN

子查询返回一张虚拟表,供外部查询和使用,但作为这种使用,子查询必须有一个别名,不然SQL引擎无法识别子查询的结果表。

SELECT * FROM (SELECT name,age FROM table2 where age >= 18) as subquery ;

----第二种

SELECT t1.name, t1.age FROM table1 AS t1 

LEFT JOIN 

SELECT name, age from table2 where age >= 18 AS t2 

ON t1.name = t2.name

聚合函数

聚合函数不是SQL语言内置的,功能是由DBMS提供实现的,但SQL定义了一些基础的标准聚合函数,这些函数是可以达到夸平台的通用基础聚合函数,被大部分DBMS实现:

  1. COUNT:计算行数
  2. SUM:计算列的综合
  3. AVG:计算列的平均值
  4. MAX:计算列的最大值
  5. MIN:计算列的最小值

除此之外,SQL还定义了部分稍微高级的聚合函数,比如EVERY、ANY、SOME等,但这些都不是被DBMS默认实现,所以不同的数据库提供的聚合函数可能有一些差异,

除此之外还有一个MID函数比较有意思,可以从字段的值里面提取指定位置的字符串。

SELECT MID(column_name, start, length) from table_name;

其中start为开始位置,而length为从开始位置开始计算提取多长。

日期函数

日期函数有助于在时间格式提取相关的值,比如YEAR、MONTH、DAY、WEEK、HOUR、MINUTE等,可以提取日期中的年、月、天、星期、小时和分钟,而还有DATEDIFF则可以计算两个日期之间的间隔,FROM_DAYS则是将天转换为日期,适用于日期相减的结果的时候使用。

除此之外,还有一些特殊的寄存器,比如CURRENT_DATE、CURRENT_TIME储存着当前的日期和当前的时间。

标量和聚合

SQL的函数可以分位聚合和标量函数,标量函数即对每一行进行计算,返回每一行的单个值,即输入多少行,返回多少行,典型的比如MONTH提取每行的月份和ROUND对输入的行的数值进行小数位设定。

聚合函数即对多行数据进行计算,并返回单个值的函数,即输入多行,返回单个值,典型的就是COUNT函数。

多表查询

多表查询有子查询、隐式JOIN和JOIN ON操作符来进行多表的查询。

子查询

比如下面的查询,想筛选部门地址为’10001’的所有员工,但是employees表没有部门的地址信息,只有departments表有,所有就可以通过子查询进行多表筛选。

SELECT * FROM employees 

WHERE DEP_ID IN

(SELECT DEPT_ID_DEP FROM departments where loc_id = '10001')

隐式JOIN

当查询中未指定连接条件(例如 ON 或 WHERE),每张表的每一行会与另一张表的每一行组合,形成笛卡尔积。

table1:

**id**	**name**

1	Alice

2	Bob

Table2:

**product_id**	**product_name**

101	Laptop

102	Smartphone

查询结果:

SELECT * FROM table1, table2;



**id**	**name**	**product_id**	**product_name**

1	Alice	101	Laptop

1	Alice	102	Smartphone

2	Bob	101	Laptop

2	Bob	102	Smartphone

但隐式JOIN可以通过条件来限定返回的内容,限定了过后,实际上是和Inner Join逻辑是相同的:

SELECT * FROM TABLE1, TABLE2 WHERE TABLE1.name = TABLE2.name;
(完)