在本教程中, 你将详细研究以下主题:
SQL和数据库简介
SQL数据类型
SQL和数据报告
- 编写SQL SELECT语句
- 项目, 选择, 加入
- 级联
- 别名
- 使用DISTINCT消除重复的行
- 限制和排序数据
- WHERE子句, 像IN, LIKE这样的通配符
- 比较运算符, 逻辑运算符(AND, OR, NOT)
- ORDER BY子句
- 使用单行功能自定义输出
- 角色功能
- 数字功能
- 日期功能
- 转换功能
- 一般功能
使用组功能报告汇总数据
- AVG, COUNT, MIN, MAX …
- 使用GROUP BY和HAVING子句
- 笛卡尔积
- 等值联接, 内部联接, 右外部联接, 左外部联接, 完全外部联接
- 什么是子查询
- 自加入
- 单行子查询
- 子查询中的组函数
- 联合, 相交, 减号
SQL与数据科学
在本部分中, 你将了解为什么数据科学家应该学习SQL。让我们看一下SQL将如何在你作为数据科学家的职业生涯中为你提供帮助:
- SQL已成为大多数数据科学工作的必备条件, 其中包括:数据分析师, BI(商业智能)开发人员, 程序员, 数据库程序员。 SQL将使你与数据库进行通信并处理数据。
- 如果你使用过Tableau之类的软件或任何其他数据报告或可视化软件, 则可能已经了解了如何将项目连接到数据库, 然后将图形和图表拖放到报告中, 仅指定字段, 其余的用于该软件。你。因此, 当你执行数据属性的拖放活动或使用图形用户界面单击一次即可完成所有操作时, 该软件的背面将运行与数据库交互的SQL。通过学习SQL, 你可以直接与数据库进行交互。
- SQL可以与所有应用程序编程语言(例如PHP, Java)一起使用。你可以通过将SQL集成到应用程序中来创建自己的数据可视化, 或者从数据库中获取数据并转换成XML, JSON格式以在Web服务或API中使用它们。
- 多年来, 数据库已经得到了发展, 随着大数据成为人们谈论的话题以及日常生活中使用的数据, NoSQL数据库正变得越来越流行。学习SQL将帮助你在数据库中打下坚实的基础, 并有助于了解何时使用结构化数据库以及何时使用NoSQL数据库并了解它们之间的差异。
SQL和数据库简介
数据库是信息的有组织的集合。要管理数据库, 我们需要数据库管理系统(DBMS)。 DBMS是一个程序, 可根据要求存储, 检索和修改数据库中的数据。
一段时间以来, 数据库的类型有所不同:分层数据库, 网络数据库, 关系数据库以及现在的NoSQL数据库。关系数据库是关系或二维表的集合。
文章图片
以下是RDBMS中使用的术语:
术语 | 描述 |
---|---|
表 | 表是RDBMS的基本存储结构。表格存储了现实世界中所有必要的所有数据。示例:员工。 |
单行或元组 | 代表特定员工所需的所有数据。表格中的每一行都可以由主键标识, 该主键不允许重复的行。 |
列或属性 | 通常指实体的特征 |
首要的关键 | 唯一标识行的字段 |
外键 | 外键是一列, 用于标识表之间的关系。外键是指另一个表中的主键。 |
文章图片
可以使用结构化查询语言或SQL访问关系数据库。每个数据库都将支持ANSI SQL(这是标准SQL), 但也将具有自己的语法以方便进行某些操作。在本教程中, 你将学习ANSI SQL, 以便可以使用所有数据库。 ANSI SQL可以分为五个部分。我将全部命名, 但这里只有两个与数据检索和DML相关的部分:
- 资料撷取:
- 选择。
- 数据处理语言(DML):
- 插入, 更新, 删除, 合并
- 数据定义语言(DDL):
- 创建, 更改, 删除, 重命名, 截断。
- 数据控制语言(DCL):
- 格兰特, 撤销。
- 交易控制:
- 提交, 回滚, 保存点。
- 甲骨文(Oracle Corporation)
- Microsoft SQL Server(Microsoft)
- MySQL(Oracle公司)
- PostgreSQL(PostgreSQL全球发展小组)
- SQLite(由D. Richard Hipp开发)
- 一种报告软件, 可让你从数据库中读取并查看数据(例如:Tableau, Microsoft BI)
- 数据库管理的GUI(例如:TOAD, Oracle的SQL开发人员, MySQL的phpmyadmin)
- 基于控制台的数据库直接接口(例如:SQL plus, 用于Oracle数据库)
而已!让我们开始学习SQL …
SQL数据类型
数据库中的每一列都有一个名称及其数据类型, 有时还具有与其关联的大小。数据库开发人员的工作是设计数据库并根据需求和数据量决定应使用哪种数据类型。
作为数据科学家, 你需要熟悉数据类型, 因为它将帮助你正确使用数据库功能并准确地编写查询。数据库中每种列的类型都有一个数据类型, 例如一个人的名字, 一些存储的文本, 数字, 存储在数据库中的图像等等。
这里将为你显示Oracle服务器, SQL服务器和MySQL服务器的基本数据类型:
文章图片
进一步阅读:
- Oracle数据类型
- MySQL数据类型
- Microsoft SQL Server数据类型
对于本教程中使用的所有SQL, 使用以下示例数据库架构:
考虑一个具有两个名为emp的表的数据库, 该表保存员工数据, 而dept表则保存有关部门的记录。
emp表包含员工编号(empno), 员工姓名(ename), 工资(sal), 佣金(comm), 职位名称(job), 经理ID(mgr), 雇用日期(hiredate)和部门编号(deptno) 。由于Manager也是雇员, 并且将具有雇员编号, 因此mgr来自其工作是” MANAGER” 的empno之一。
部门表具有部门编号(deptno), 部门名称(dname)和部门位置(loc)。
文章图片
请注意, 不同的数据库具有不同的日期格式。此处的DD-MON-YY是Oracle数据库的默认日期格式。 Microsoft SQL Server和MySQL的默认格式为YYYY-MM-DD。
你的数据库表可能有所不同, 因此你仅需根据表名和属性名进行调整。在本教程中, 你将仅从数据库中读取数据, 而不是写入, 更新或创建新表和对象。因此, 不用担心任何数据丢失或更改!
信息:模式是属于用户的对象的集合, 例如表, 函数, 过程, 视图在上面的数据库架构中, 你可以看到emp表具有用于实体Employee的六个属性。表部具有实体部门的三个属性。
使用SELECT语句检索数据 SELECT语句从数据库中检索信息。使用SELECT语句, 你可以执行以下操作:
1.投影:你可以使用SQL中的投影功能在表中选择要由查询返回的列。你可以根据需要在表中选择尽可能少的列。
2.选择:你可以使用SQL中的选择功能来选择要查询返回的表中的行。
你可以使用各种条件来限制看到的行。
3.联接:你可以使用SQL中的联接功能, 通过在表之间创建链接来将存储在不同表中的数据聚集在一起。
基本的SELECT语句允许你指定要从哪个表中的哪些列。 SELECT子句指定列, 表达式, 而FROM子句指定从哪个表获取数据。
例如, 所有雇员的名字是什么, 他们的工作是什么?上面的SQL查询将根据上述数据库模式为你提供以下输出:
名字 | 工作 |
---|---|
一个 | 推销员 |
乙 | 经理 |
C | 经理 |
SELECT *FROM employee;
The output will be:EMPNO ENAMEJOBMGR HIREDATESALCOMMDEPTNO---------- ---------- --------- ---------- --------- ---------- ---------- ----------7369 SMITHCLERK7902 17-DEC-80800207499 ALLENSALESMAN7698 20-FEB-811600300307521 WARDSALESMAN7698 22-FEB-811250500307566 JONESMANAGER7839 02-APR-812975207698 BLAKEMANAGER7839 01-MAY-81285030
编写SQL语句的一些技巧:SQL语句不区分大小写将子句写在单独的行上以提高可读性你可以在一行或多行上写SQL语句你还可以在日期和数字数据上使用+, -, /, *运算符创建表达式以生成所需的数据。例如, 要求你找出所有雇员工资的20%。查询将如下所示:
SELECT ename, sal*(20/100)FROM employee;
Output:ENAMESAL*(20/100)---------- ------------SMITH160ALLEN320WARD250JONES595BLAKE570
信息:括号用于说明表达式除法和乘法的优先级高于加法和减法。如果出现相同的优先级, 则从左到右评估表达式NULL值在数据库中的处理方式有所不同。 NULL值表示该值是未知的。使用NULL执行的任何操作都将导致NULL。不同的数据库具有不同的功能来处理null。在MySQL, Microsoft SQL Server和Oracle中使用一个通用函数来处理NULL。
SELECT ename, sal+COALESCE(comm, 0)FROM employee;
Output:ENAMESAL+COALESCE(COMM, 0)---------- --------------------SMITH800ALLEN1900WARD1750JONES2975BLAKE2850
列别名和串联 你可以在上面的输出中看到, 列名与数据库字段或你选择的表达式相同。有时, 在生成报告时, 你想要给标题指定自己的名称。这可以使用别名来完成。
SELECT ename AS "Emp Name", sal*(20/100) as "20% of Salary"FROM employee;
Output:Emp Name20% of Salary---------- ------------SMITH160ALLEN320WARD250JONES595BLAKE570
当你给别名提供空格时, 必须使用双引号。否则, 无需在AS后面加上双引号。有时, 你也可以省略关键字AS。
你可以通过串联格式化输出。你可以使用CONCAT函数或||等运算符在输出中添加自己的语句。或+(取决于供应商数据库):
- Oracle支持CONCAT()和||但是CONCAT()仅接受两个参数。你必须使用嵌套的CONCAT()。
- MySQL使用CONCAT()
- Microsodt SQL Server使用’ +’ 运算符和CONCAT()。
从雇员中选择CONCAT(CONCAT(‘ 工资的20%, ename), CONCAT(‘ 是’ , sal(20/100)))作为” 工资的20%” ; MySQL和Microsoft SQL Server:SELECT CONCAT(‘ , ename, ‘ 的’ 20%工资是’ , sal(20/100))作为来自员工的” 20%工资” ;所有将导致相同的输出:
20% of salary-----------------------------------------------------------------------20% of salary of SMITH is 16020% of salary of ALLEN is 32020% of salary of WARD is 25020% of salary of JONES is 59520% of salary of BLAKE is 570
使用DISTINCT消除重复的行
SELECT deptnoFROM employee;
Above query will result in:DEPTNO----------2030302030
这里的deptno 20和30在重复。你可以通过在SELECT子句中使用DISTINCT关键字来消除此类行。
SELECT distinct ename, deptno, jobFROM employee;
DEPTNO----------3020
限制和排序数据 WHERE子句用于在某些条件下过滤数据。
查找所有有工作秘书的员工:
SELECT ename, jobFROM employeeWHERE job='CLERK';
ENAMEJOB---------- ---------SMITHCLERK
【SQL(报告和分析)】你可能想用不同的条件过滤结果。对于此运算符, 使用条件符号和特定关键字:
文章图片
如上面使用=的查询所示, 使用=, < > , !=, > =, < =, > , < 很简单。
AND&OR语法:SELECT column1, column2, .. FROM table_name WHERE condition1 AND condition2 AND condition 3 … ;
SELECT column1, column2, .. FROM table_name WHERE condition1 OR condition2 OR condition 3 … ; 查找职位为MANAGER并且属于部门30的员工的姓名:
SELECT enameFROM employeeWHERE job='MANAGER' AND deptno=30;
ENAME----------BLAKE
SELECT enameFROM employeeWHERE job='MANAGER' OR deptno=30;
ENAME----------ALLENWARDJONESBLAKE
NOT语法:SELECT column1, column2, … FROM table_name WHERE NOT条件;查找所有非SALESMAN工作的员工:
SELECT ename, jobfrom employeeWHERE NOT job='SALESMAN';
ENAMEJOB---------- ---------SMITHCLERKJONESMANAGERBLAKEMANAGER
你可以使用所有三个AND, OR和NOT运算符来创建复杂条件。优先级是:
- 不
- 和
- OR
SELECT ename, jobfrom employeeWHERE NOT job='SALESMAN' AND sal>
800;
ENAMEJOB---------- ---------JONESMANAGERBLAKEMANAGER
在这里, NOT首先执行, NOT之后执行, 并且被评估。
其他方便的条件运算符如下所示:
之间:
SELECT *FROM employeeWHERE sal BETWEEN 1000 AND 2000;
EMPNO ENAMEJOBMGR HIREDATESALCOMMDEPTNO---------- ---------- --------- ---------- --------- ---------- ---------- ----------7499 ALLENSALESMAN7698 20-FEB-811600300307521 WARDSALESMAN7698 22-FEB-81125050030
喜欢:
LIKE使用两个通配符:百分比%和下划线_表示模式中的字符数。
- %表示任何零个, 一个或多个字符
- %M%:匹配在任何位置具有M的任何字符串
- M%:匹配值开头为M
- %M:匹配值以M结尾
- M%A:以M开头, 以A结尾
- _指定在已知字符之前或之后的未知字符数。下划线是一个字符。
- _r%:匹配值, r在第二位置。
SELECT *FROM employeeWHERE ename LIKE 'B%';
EMPNO ENAMEJOBMGR HIREDATESALCOMMDEPTNO---------- ---------- --------- ---------- --------- ---------- ---------- ----------7698 BLAKEMANAGER7839 01-MAY-81285030
获取所有以” A” 开头并且在” A” 之后的任何位置都具有” E” 的员工的姓名:
SELECT *FROM employeeWHERE ename LIKE 'A%E%';
EMPNO ENAMEJOBMGR HIREDATESALCOMMDEPTNO---------- ---------- --------- ---------- --------- ---------- ---------- ----------7499 ALLENSALESMAN7698 20-FEB-81160030030
IN(值1, 值2, 值3 ..):
IN()函数可以采用一个, 两个或多个值, 并允许你将列与WHERE子句中括号中的给定值进行匹配:
SELECT ename, job, hiredateFROM employeeWHERE job IN ('CLERK', 'SALESMAN');
ENAMEJOBHIREDATE---------- --------- ---------SMITHCLERK17-DEC-80ALLENSALESMAN20-FEB-81WARDSALESMAN22-FEB-81
你还可以在IN()中使用SELECT语句, 该语句将返回一些值。例如:
SELECT ename, job, hiredateFROM employeeWHERE deptno IN (select deptno FROM department WHERE loc='CHICAGO');
ENAMEJOBHIREDATE---------- --------- ---------ALLENSALESMAN20-FEB-81WARDSALESMAN22-FEB-81BLAKEMANAGER01-MAY-81
IN()中的SELECT语句也称为子查询。本教程后面的内容将进一步介绍子查询!
一片空白:
IS NULL用于检查给定属性中的NULL值。例如, 查找所有没有佣金的员工:
SELECT ename, job, salFROM employeeWHERE comm IS NULL;
ENAMEJOBSAL---------- --------- ----------SMITHCLERK800JONESMANAGER2975BLAKEMANAGER2850
如果要获取获得佣金的雇员的姓名, 则将使用IS NOT NULL:
SELECT ename, job, sal, commFROM employeeWHERE comm IS NOT NULL;
ENAMEJOBSALCOMM---------- --------- ---------- ----------ALLENSALESMAN1600300WARDSALESMAN1250500
要过滤使用日期列的结果, 你必须使用默认日期格式。如果要使用其他格式, 则需要应用日期函数, 你将在本教程的后面看到。查找1981年2月21日之后被雇用的所有雇员:
(此处使用Oracle默认日期格式)
SELECT ename, job, sal, commFROM employeeWHERE hiredate>
'21-FEB-81';
ENAMEJOBSALCOMM---------- --------- ---------- ----------WARDSALESMAN1250500JONESMANAGER2975BLAKEMANAGER2850
可以结合使用以上所有运算符来生成复杂的条件表达式, 但是你必须小心使用优先级。优先级是评估运算符的顺序。以下是不同数据库的优先级规则:
- Microsoft Transact-SQL运算符优先级
- Oracle 10g条件优先级
- Oracle MySQL 9运算符优先级
- PostgreSQL运算符优先级
- SQLite运算符优先级
SELECT ename, job, sal, commFROM employeeWHERE deptno=ANY(SELECT deptno from dept WHERE loc='NEW YORK');
SELECT ename, job, sal, commFROM employeeWHERE deptno=ALL(SELECT deptno from dept WHERE dname='SALES');
请注意, 在上面的示例中使用了子查询。稍后, 你将了解有关子查询的更多信息。
使用ORDER BY CLAUSE排序结果 你可以按表的任何属性或多个属性对结果升序(ASC)或降序(DESC)进行排序。你还可以按在SELECT子句中指定的别名进行排序:
SELECT ename, job, sal, commFROM employeeWHERE hiredate>
'21-FEB-81'ORDER BY sal desc;
ENAMEJOBSALCOMM---------- --------- ---------- ----------JONESMANAGER2975BLAKEMANAGER2850WARDSALESMAN1250500
注意:默认顺序由ASC升序, 你无需指定ASC。
SELECT ename, job, sal, commFROM employeeWHERE hiredate>
'21-FEB-81'ORDER BY sal;
ENAMEJOBSALCOMM---------- --------- ---------- ----------WARDSALESMAN1250500BLAKEMANAGER2850JONESMANAGER2975
你可以在ORDER BY子句中指定多个列, 这些列将按照指定的列的顺序执行。例如, 首先按升序对员工进行排序, 然后按降序命名:
SELECT ename, job, sal, comm, deptnoFROM employeeWHERE hiredate>
'21-FEB-81'ORDER BY deptno ASC, ename DESC;
ENAMEJOBSALCOMMDEPTNO---------- --------- ---------- ---------- ----------JONESMANAGER297520WARDSALESMAN125050030BLAKEMANAGER285030
使用单行功能自定义输出
所有RDBMS中都有许多函数可以帮助你执行常见任务, 例如获取字符串的长度, 连接字符串, 格式化函数, 数学函数等。SQL中有两种类型的行函数:
- 单行功能
- 多行功能
这些函数应用于每行, 并每行返回结果。 CONCAT()是字符操作单行函数。这些可以在SELECT, WHERE和ORDER BY子句中使用。所有RDBMS中都有以下单行函数:
- 角色操作功能
- 日期和时间功能
- 数字功能
- 转换功能
让我们浏览每个类别:
角色操纵功能 LOWER():将字符串转换为小写。
SELECT lower(ename) as enameFROM employee;
ENAME----------smithallenwardjonesblake
UPPER():将字符串转换为小写。
SELECT upper(ename) as enameFROM employee;
ENAME----------SMITHALLENWARDJONESBLAKE
SUBSTR()[Oracle, MySQL]:返回指定的子字符串SUBSTR(string, start-position, length)
SUBSTRING()[SQL Server]:返回指定的子字符串SUBSTRING(字符串, 开始位置, 长度)。
SELECT SUBSTR(ename, 2, 3) as substr_enameFROM employee;
对于SQL Server, 只需将函数名称替换为SUBSTRING即可。
SUBSTR_ENAME------------MITLLEARDONELAK
LENGTH()[Oracle, MySQL]:以括号返回字符串的长度
LEN()[SQL Server]:在括号中返回字符串的长度
SELECT LENGTH(ename) as len_enameFROM employee;
对于SQL Server, 只需将函数名称替换为LEN。
LEN_ENAME----------55455
诸如将字符串填充到左侧或右侧, 替换等功能在不同数据库的语法上开始有所不同。三个供应商数据库的字符和字符串函数列表:
- Oracle字符和字符串函数
- Microsoft SQL服务器
- MySQL字符和字符串函数
功能名称 | 函数 |
---|---|
轮数(m, n): | 将值m舍入为指定的n个小数位。 |
ABS(m, n): | 返回数字的绝对值 |
楼层(n): | FLOOR返回等于或小于n的最大整数。 |
MOD(m, n): | 返回m除以n的余数(在SQL Server中不可用, 但使用%运算符:35%6) |
SELECT ROUND(45.926, 2), MOD(11, 5), FLOOR(34.4), ABS(-24) from dual;
OUTPUT:ROUND(45.926, 2)MOD(11, 5) FLOOR(34.4)ABS(-24)--------------- ---------- ----------- ----------45.9313424
MySQL:
SELECT ROUND(45.926, 2), MOD(11, 5), FLOOR(34.4), ABS(-24);
SQL Server:
SELECT ROUND(45.926, 2) as round, 11%5 as mod, FLOOR(34.4) as floor, ABS(-24) as abs;
三个供应商数据库的数字功能列表:
- Oracle Number函数
- Microsoft SQL服务器
- MySQL数字函数
SELECT ename, to_char(hiredate, 'DD, MONTH YYYY') as Hiredate, to_char(hiredate, 'DY') as Dayfrom employee;
ENAMEHiredateDAY---------- -------------------------------------------- ------------SMITH17, DECEMBER1980WEDALLEN20, FEBRUARY1981FRIWARD22, FEBRUARY1981SUNJONES02, APRIL1981THUBLAKE01, MAY1981FRI
每个数据库服务器都有很多转换功能。为了进一步阅读和探索, 以下是指向不同数据库服务器转换功能的链接:
- Microsoft SQL Server转换功能
- Oracle服务器转换功能
- MySQL转换功能
文章图片
- Oracle日期和时间功能
- MySQL日期和时间函数
- Microsoft SQL Server日期和时间功能
分组功能或多行功能应用于组, 并且每组返回一个结果。当你想了解诸如每季度的总销售额, 一段时间内产品的平均价格, 公司本月获得的最高投资等事实时, 将需要使用小组功能。
使用组功能报告汇总数据 GROUP BY子句用于对经常与COUNT, MAX, MIN, AVG和SUM之类的函数一起使用的结果进行分组。 GROUP BY的语法为:
SELECT column_name(s)FROM table_nameWHERE conditionGROUP BY column_name(s)HAVING conditionORDER BY column_name(s);
你必须记住GROUP BY子句的一些要点:
- 别名不能在GROUP BY子句中使用
- WHERE子句始终位于GROUP BY之前
- HAVING子句将在GROUP BY之后, 并将对组函数应用条件。
- ORDER BY子句始终会最后出现
计算所有以” A” 开头的员工:
SELECT count(ename)FROM employeeWHERE ename LIKE 'A%';
Output:COUNT(ENAME)------------1
查找表员工的总薪水, 平均薪水, 最低薪水和最高薪水:
SELECT sum(sal) as "TOTAL SAL", avg(sal) as "AVG SAL", min(sal) as "MIN SAL", max(sal) as "MAX SAL"FROM employee;
TOTAL SALAVG SALMIN SALMAX SAL---------- ---------- ---------- ----------947518958002975
你可能希望将每个部门的上述结果分组:
SELECT sum(sal) as "TOTAL SAL", avg(sal) as "AVG SAL", min(sal) as "MIN SAL", max(sal) as "MAX SAL", deptnoFROM employeeGROUP BY deptno;
TOTAL SALAVG SALMIN SALMAX SALDEPTNO---------- ---------- ---------- ---------- ----------57001900125028503037751887.5800297520
你还可以使用以下函数来计算值的方差和标准偏差:
对于Oracle和MySQL | MS SQL服务器 |
---|---|
从table_name中选择STDDEV(column_name); | 从table_name中选择STDEV(column_name); |
SELECT VARIANCE(column_name)FROM table_name; | 从表名中选择VAR(column_name); |
查找每个部门中每个工作的薪水总和:
SELECT sum(sal) as "TOTAL SAL", deptno, jobFROM employeeGROUP BY deptno, job;
TOTAL SALDEPTNOJOB---------- ---------- ---------80020CLERK285030SALESMAN297520MANAGER285030MANAGER
你可以使用HAVING子句限制分组结果。它仅用于组条件。
注意:请勿使用WHERE在组功能上应用条件。
SELECT sum(sal) as "TOTAL SAL", deptno, jobFROM employeeGROUP BY deptno, jobHAVING sum(sal)>
1000ORDER BY sum(sal);
TOTAL SALDEPTNOJOB---------- ---------- ---------285030SALESMAN285030MANAGER297520MANAGER
显示来自多个表的数据 在本节中, 将讨论以下联接:
- 笛卡尔积/交叉联接
- 内联/ EquiJoins
- 自然连接
- 外连接(左, 右, 全)
- 自我加入
文章图片
要生成上述报告, 你需要链接员工表和部门表并从两者中获取数据。为此, 在SQL中使用联接。
笛卡尔积/交叉联接:
当关系R的每个元组与关系S的每个元组创建一个组合时, 就会形成笛卡尔积。
文章图片
笛卡尔积运算(也称为” 交叉联接” )将两个表相乘以形成一个关系, 该关系由两个表中所有可能的元组对组成。如果一个关系说, R具有I个具有M个属性的元组, 而另一个关系说S具有J个元组N个属性, 笛卡尔积将具有IxJ个具有M + N个属性的元组。也可以使用SQL投诉CROSS JOIN来形成笛卡尔乘积。
SELECT empno, ename, dnameFROM employee, department;
ORSELECT empno, ename, dnameFROM employee CROSS JOIN department;
EMPNOENAMEDNAME---------- ---------- --------------7369SMITHACCOUNTING7499ALLENACCOUNTING7521WARDACCOUNTING7566JONESACCOUNTING7698BLAKEACCOUNTING7369SMITHRESEARCH7499ALLENRESEARCH7521WARDRESEARCH7566JONESRESEARCH7698BLAKERESEARCH7369SMITHSALESEMPNOENAMEDNAME---------- ---------- --------------7499ALLENSALES7521WARDSALES7566JONESSALES7698BLAKESALES
已选择15行。
由于雇员表包含5个元组, 部门包含3个元组, 因此笛卡尔积具有5× 3 = 15行。在以下情况下会生成笛卡尔积:
- 不使用联接条件
- 连接条件无效或格式不正确
笛卡尔积用于仿真大量数据以进行测试。
*内部加入/等额加入:
内部联接或等联接(Oracle开发人员使用的术语)使用主键和外键关系联接两个或多个表:
SELECT ename, dnameFROM employee e, department dWHERE e.deptno=d.deptno;
ORSELECT ename, dnameFROM employee eJOIN department dON e.deptno=d.deptno;
ENAMEDNAME---------- --------------SMITHRESEARCHALLENSALESWARDSALESJONESRESEARCHBLAKESALES
在上面的查询中, deptno是部门表中的主键, 而雇员表中的外键。你可以使用逻辑操作来添加其他条件, 如上节所述。
记住JOINS的要点:如果同一列名出现在多个表中, 则该列名必须以表名为前缀。否则, 最好这样做也是为了提高清晰度。要将n个表连接在一起, 你至少需要n-1个连接条件。例如, 要联接四个表, 至少需要三个联接。表别名:表别名(例如在FROM员工e, 部门d中使用), 其中e和d是表别名, 以使数据库引擎更容易识别列来自哪个表, 尤其是当多个列中存在相同的列时一个涉及的表, 因为否则将给出歧义列的错误。并且节省了一次又一次写大表名的时间。
你还可以创建基于相等条件以外的条件的连接表的无连接。考虑另一个表salgrade, 该表具有有关基于薪金的雇员级别的信息:
文章图片
你想根据薪水找出每个员工的等级, 而等级存储在salgrade表中, 而薪水存储在employee表中:
SELECT e.ename, e.sal, s.gradeFROM employee e, salgrade sWHERE e.sal between s.losal AND s.hisal;
ENAMESALGRADE---------- ---------- ----------JONES29754BLAKE28504ALLEN16003WARD12502SMITH8001
示例:要求你提供雇员的姓名, 工资, 职级和部门名称。现在, 你知道, 薪水存储在员工表中, 薪金存储在薪级表中, 部门名称存储在部门表中, 你将需要将三个表结合在一起:
SELECT e.ename, e.sal, d.dname, s.gradeFROM employee e, department d, salgrade sWHERE e.deptno=d.deptnoAND e.sal BETWEEN s.losal AND s.hisal;
Output:ENAMESAL DNAMEGRADE---------- ---------- -------------- ----------JONES2975 RESEARCH4BLAKE2850 SALES4ALLEN1600 SALES3WARD1250 SALES2SMITH800 RESEARCH1
在上面的示例中, 涉及到三个表, 并且两个连接条件之一是非静态连接。
自然加入:
自然联接允许数据库通过匹配具有相同名称的列来自动联接表。如果列的名称相同但数据类型不同, 则将给出错误。
语法:SELECT FROM table1 NATURAL JOIN table2; 从员工NATURAL JOIN部门中选择;由于自然联接本身会找到匹配的列, 因此它可能会找到多个具有相同名称的匹配列, 但可能具有不同的数据类型, 这可能会导致错误。因此, USING子句用于指定在其上进行均等联接的列。
注意:NATURAL JOIN和USING是两个不同的子句, 分别使用。一个不能在另一个互斥的情况下使用。
SELECT e.ename, d.dname, e.salFROM employee e JOIN department dUSING (deptno)WHERE deptno=20;
output:ENAMEDNAMESAL---------- -------------- ----------SMITHRESEARCH800JONESRESEARCH2975
USING子句中的列不能在SQL语句中的任何地方使用表名或表前缀。例如以下不正确:
SELECT e.ename, d.dname, e.salFROM employee e JOIN department dUSING (d.deptno)WHERE d.deptno=20;
d.deptno错误。仅应使用deptno。外连接:
有三个外部联接:
- 左外部联接:两个表之间的联接返回内部联接的结果以及左表的不匹配行, 称为左外部联接
- 右外部联接:两个表之间的联接返回内部联接的结果以及右表的不匹配行, 称为右外部联接。
- 完全外部联接:两个表之间的联接返回内部联接的结果以及右表的不匹配行, 称为RIGHT OUTER JOIN。
SELECT e.ename, s.gradeFROM salgrade s LEFT OUTER JOIN employee eON e.sal BETWEEN s.losal AND s.hisal;
Output:ENAMEDEPTNO DNAME---------- ---------- --------------SMITH20 RESEARCHJONES20 RESEARCHALLEN30 SALESWARD30 SALESBLAKE30 SALES.sal BETWEEN s.losal AND s.hisal;
Output:ENAMEDEPTNO DNAME---------- ---------- --------------SMITH20 RESEARCHJONES20 RESEARCHALLEN30 SALESWARD30 SALESBLAKE30 SALESSELECT e.ename, d.deptno, d.dname
FROM employee e RIGHT OUTER JOIN department dON e.deptno=d.deptno;
output:ENAMEDEPTNO DNAME---------- ---------- --------------SMITH20 RESEARCHALLEN30 SALESWARD30 SALESJONES20 RESEARCHBLAKE30 SALES10 ACCOUNTINGSELECT e.ename, d.deptno, d.dname
FROM employee e FULL OUTER JOIN department dON e.deptno=d.deptno;
Output:ENAMEDEPTNO DNAME---------- ---------- --------------SMITH20 RESEARCHALLEN30 SALESWARD30 SALESJONES20 RESEARCHBLAKE30 SALES10 ACCOUNTING
部门表在deptno 10上有一个不匹配的行, 在雇员表中没有找到不匹配的行。同样, 五年级的薪水表中有一行不匹配。
自加入:
在某些情况下, 你想将表与其自身联接。例如, employee表包含有关所有员工(包括经理)的信息(请参阅上面的表employee)。如果要求你找出员工及其经理, 那么你将需要将一个表自身连接起来。通过以下方式进行自我联接:
SELECT e.ename as Employee, m.ename as ManagerFROM employee e, employee mWHERE e.mgr=m.empno;
EMPLOYEEMANAGER---------- ----------ALLENBLAKEWARDBLAKE
使用子查询解决查询 子查询是查询中的查询。子查询可用于将大型查询细分为多个段。子查询可以嵌套, 并且可以在以下SQL子句中使用:
- 其中
- 从
- 拥有
- 找到詹姆斯的薪水
- 比较詹姆斯与所有员工的薪水
SELECT empno, enameFROM employeeWHERE sal>
(SELECT sal from employee where ename='JAMES');
子查询的类型:
- 单行子查询:仅从内部SELECT语句返回一行的查询。
- 多行子查询:从内部SELECT语句返回多行的查询。
要记住的要点:将子查询括在括号中。将子查询放在比较运算符的右侧。对单行子查询使用单行运算符(> , < , > =, < =, < > )。对多个行子查询使用多个行运算符(IN, ANY, ALL)。单行子查询:
要求你查找职位名称与empno 7521相同的员工姓名
SELECT ename, jobFROM employeeWHERE job=(SELECT job FROM employee WHERE empno=7521);
ENAMEJOB---------- ---------ALLENSALESMANWARDSALESMAN
选择最高薪水高于部门20最高薪水的部门最高薪水
SELECT deptno, max(sal)FROM employeeGROUP BY deptnoHAVING max(sal)>
=(SELECT max(sal) FROM employee WHERE deptno=20);
DEPTNOMAX(SAL)---------- ----------202975
多行子查询:
查找薪水等于担任经理职位的员工的薪水的员工。这将是一个多行子查询, 因为该子查询可以返回多个行。
SELECT ename, job, salFROM employeeWHERE sal IN (SELECT sal FROM employee WHERE job='MANAGER');
ENAMEJOBSAL---------- --------- ----------JONESMANAGER2975BLAKEMANAGER2850
在FROM子句中使用子查询时, 它充当临时表, 该表在存储上实际上不存在, 但是是数据视图。例如:
SELECT e.ename, e.job, e.salFROM employee e, (SELECT deptno FROM department WHERE loc='DALLAS') dWHERE e.deptno=d.deptno;
ENAMEJOBSAL---------- --------- ----------SMITHCLERK800JONESMANAGER2975
使用SET运算符 在SQL Set中, 运算符用于将多个查询的结果合并为一个结果。它在数学及其运算中使用了集合论, 例如UNION, MINUS, INTERSECT。在这里, 你将看到如何使用SET运算符来优化查询。在本教程中, 将讨论以下SET运算符。
信息:使用SET运算符的查询称为复合语句。
- UNION和UNION ALL
- 相交
- EXCEPT(SQL标准)和MINUS(特定于Oracle)
考虑R和S的两个关系(表), 然后UNION从R中选择所有行, 从S中选择所有行, 以消除重复。返回的行数可以是最大r + s, 其中r是R中的行数, s是S中的行数。
选择所有部门名称, 包括在1999年10月23日之前雇用的员工的部门名称
SELECT dnameFROM departmentUNIONSELECT dnameFROM department, employeeWHERE department.deptno=employee.deptno AND employee.hiredate<
to_date('23-OCT-1999');
DNAME--------------ACCOUNTINGOPERATIONSRESEARCHSALES
要记住UNION的要点:在查询中使用的所有SELECT语句中, 所选的列数和数据类型必须相同。列的名称不必相同。输出以SELECT子句的第一列的升序排序。在重复检查期间不会忽略NULL值。UNION ALL合并一个或多个查询的结果, 并且不会删除重复项, 因此不能使用DISTINCT关键字。考虑另一个表emp, 其中包含2000年以来的雇员。从emp和employee表中获取所有雇员编号, 姓名和职位:
SELECT empno, ename, jobFROM employeeUNION ALLSELECT empno, ename, jobFROM emp;
EMPNOENAMEJOB---------- ---------- ---------7369SMITHCLERK7499ALLENSALESMAN7521WARDSALESMAN7566JONESMANAGER7698BLAKEMANAGER7369SMITHCLERK7499ALLENSALESMAN7521WARDSALESMAN7566JONESMANAGER7654MARTINSALESMAN7698BLAKEMANAGEREMPNOENAMEJOB---------- ---------- ---------7782CLARKMANAGER7788SCOTTANALYST7839KINGPRESIDENT7844TURNERSALESMAN7876ADAMSCLERK7900JAMESCLERK
相交
交集遵循与集合论相同的规则, 以给出两个集合的共同值。考虑两个关系R和S, 然后INTERSECT将返回在R和S中都通用的所有元组的集合。
SELECT empno, ename, jobFROM employeeINTERSECTSELECT empno, ename, jobFROM emp;
EMPNO ENAMEJOB---------- ---------- ---------7369 SMITHCLERK7499 ALLENSALESMAN7521 WARDSALESMAN7566 JONESMANAGER7698 BLAKEMANAGER
INTERSECT要记住的要点:在查询中使用的所有SELECT语句中, 所选的列数和数据类型必须相同。列的名称不必相同。 INTERSECT不会忽略NULL值减号:
EXCEPT(在SQL Server中使用)和MINUS(针对Oracle)具有相同的功能。该功能是选择第一个查询而不是第二个查询选择的所有不同行。要了解此运算符, 请考虑下表:
文章图片
说, 你需要找到数量在1到100之间但数量在50-75之间的产品。如果你使用的是SQL Server, 则在这里使用EXCEPT, 如果你使用的是Oracle服务器, 则使用MINUS。
SELECT prod_name, qtyFROM productsWHERE qty BETWEEN 1 AND 100EXCEPTSELECT prod_name, qtyFROM productsWHERE qty BETWEEN 50 AND 75;
对于Oracle服务器:
SELECT prod_name, qtyFROM productsWHERE qty BETWEEN 1 AND 100MINUSSELECT prod_name, qtyFROM productsWHERE qty BETWEEN 50 AND 75;
PROD_NAMEQTY-----------------------COLGATE1SENSODYNE100SENSODYNE TOOTHBRUSH30
EXCEPT / MINUS要记住的要点:在查询中使用的所有SELECT语句中, 所选的列数和数据类型必须相同。列的名称不必相同。 WHERE子句中的所有列都必须在SELECT子句中, MINUS运算符才能起作用。恭喜你!
教程到此结束。在本教程中, 你学习了很多SQL, 可帮助你在数据科学之旅中掌握SQL。 SQL用于从数据库生成报告。你已在本教程中学习了数据库和SQL的基础, 常用的数据类型, 可帮助你实现格式报告的功能, 汇总创建结果的结果以及如何根据自己的需要从数据库中的不同表收集数据的方法要求!本教程是专门为数据科学学习者设计的, 它们不仅可以帮助他们使用关系数据库, 而且可以顺利地学习NoSQL数据库以及如何在大数据研究中使用SQL技能。
如果你想了解有关SQL的更多信息, 请参加srcmini的免费SQL for Data Science入门课程。
参考文献
- Tanveer Zahid Khan(Bahria大学计算机科学系高级助理教授)对Oracle 10g-SQL讲座的介绍
- https://docs.oracle.com/cd/B19306_01/server.102/b14200/operators005.htm
- https://en.wikipedia.org/wiki/Set_operations_(SQL)#EXCEPT_operator
- https://www.w3schools.com/sql/sql_datatypes.asp
- https://docs.oracle.com/cd/B28359_01/server.111/b28318/datatype.htm#CNCPT012
推荐阅读
- 推断神经网络的层数和神经元(图解)
- Python列表(划分为给定大小的块)
- 用PyTorch研究张量
- Android ListView Animation 4种动画效果(贴上了GIF图)
- Android在滚动列表中实现视频的播放 ListViewRecyclerView
- ???????????????app??????????????????Activity
- APP注册邀请码
- 实现mapper接口注入的两种方式,以及后台的使用区别
- 移动 APP 网络优化概述