ITPub博客

首页 > 数据库 > 数据库开发技术 > SQL教程#1Day:数据检索

SQL教程#1Day:数据检索

原创 数据库开发技术 作者:jackzhang 时间:2024-03-27 06:30:00 0 删除 编辑

引言

SQL(Structured Query Language)是用于管理关系型数据库的标准化语言。数据检索是SQL中最基础、最常用的操作之一,它允许用户从数据库中提取所需的数据。本教程将介绍如何使用SQL语句进行数据检索,包括基本的SELECT语句、条件筛选、随机记录查询、空值检索等内容。无论是初学者还是有一定经验的数据库开发人员,都可以通过本教程快速掌握SQL数据检索的基本原理和操作技巧。通过学习本教程,读者将能够编写简单而有效的SQL查询,从而更好地利用和管理数据库中的信息。

从今天开始,我将写一个SQL教程系列,该教程系列旨在SQL语句的实际操作,包括简单的数据检索、查询排序、多表处理、字符串处理、数值处理、日期运算及操作、高级搜索等内容,全是实操干货,基本不涉及很泛的纯理论。

🆗,话不多说,下面开始我们的第一讲——数据检索。

数据准备

整个教程都将以下面两个简单的表作为示例数据:

  • 员工表(emp)

  • 部门表(dept)

这两个表的创建及数据填充脚本我已经整理好,需要的朋友可以在文末获取。

数据检索

本教程将重点介绍基本的SELECT语句。对基础知识有扎实的理解是很重要的(毕竟俗语有云万丈高楼平地起嘛😄),因为这里涵盖的许多主题不仅是后续教程中更困难内容的基础,而且在日常SQL中也经常用到。

检索单张表的所有行和列

  • 问题:假设你有一张表,想看它里面的所有数据(行和列)。
  • 实现:在SELECT语句中使用星号(*)或手动列出所有列即可
SELECT *
FROM emp;
-- or
SELECT empNo, eName, job, mgr, hireDate, sal, comm, deptNo
FROM emp;
  • 解释:在SQL中,*号表示选择所有列。在交互式执行的特殊查询中,使用SELECT *更容易。但是, 在编写程序代码时,最好单独指定需要返回的具体列名;同时,显式指定列名也更加有助于代码的调试。

检索满足特定条件的行

  • 问题:你有一张表,但是只想看满足特定条件的行。比如,查看部门号为10的所有员工信息。
  • 实现:可以在WHERE子句中指定筛选条件即可。
SELECT *
FROM emp
WHERE deptNo = 10;
  • 解释:WHERE子句允许你只检索感兴趣的行。如果WHERE子句中的表达式对任何一行都为真,则返回该行。

检索满足多个条件的行

  • 问题:检索部门号为10的所有员工,以及任何赚取了佣金的员工,以及部门20中薪水不超过2000美金的员工。
  • 实现:我们可以把条件拆成三个:
  1. 部门号为10
  2. 佣金不为空
  3. 部门号为20且薪水不超过2000美金

这样逻辑就很清晰,代码实现就比较简单:

SELECT *
FROM emp
WHERE deptNo = 10
   OR comm IS NOT NULL
   OR (deptNo = 20 AND sal <= 2000);
  • 解释:通过逻辑词AND和OR以及圆括号可以控制条件的组合和优先级,从而正确筛选出符合要求的数据行。

检索表中指定列(列的子集)

  • 问题:假设你有一张表,并且只想看特定列的值,而不是所有列。比如,只想看员工表中员工的姓名、部门号和薪水。
  • 实现:在SELECT语句中指定目标列即可。
SELECT eName, deptNo, sal
FROM emp;
  • 解释:通过在SELECT子句中指定列,可以确保不返回多余的数据 。这在通过网络检索数据时尤其重要,因为它可以节省检索不必要的数据而消耗的时间成本。

给列提供有意义的名称(列别名)

  • 问题:有些时候可能你希望更改查询返回的列的名称,以便它们更易于阅读和理解。考虑下面这个查询,它返回每个员工的工资和佣金:
SELECT sal, comm
FROM emp;

如果不是熟悉表字段含义的人,看到这样的代码可能造成误解,他们会想“sal”是什么?是销售(sale)的缩写吗?还是某个人的名字?另外“comm”又是什么?是交流、通信(communication)?所以,这个时候给列一个可读性更强的名称就显得很有必要,这会消除交流障碍和误解。

  • 实现:在列后面跟AS alias_name(AS关键字可选)就表示给对应的列一个别名。
SELECT eName AS employee_name,
       sal AS salary,
       comm AS commission
FROM emp;
  • 解释:使用AS关键字为查询返回的列指定新名称为对这些列进行别名。你给的新名字就被称为别名。创建良好的别名可以让其他人对查询及其结果更容易理解。

在 WHERE 子句中引用列的别名

  • 问题:你已经学会使用别名为结果集提供更有意义的列名,这个时候你可能希望在WHERE子句中使用别名来排除掉某些行。比如:
SELECT eName AS employee_name,
       sal AS salary,
       comm AS commission
FROM emp
WHERE salary < 5000;

执行上面的查询,将会报语法错误:

这涉及到SQL查询语句的执行顺序(具体可阅读我的另一篇文章:10倍提升你的SQL查询速度)。因为WHERE子句在SELECT子句之前执行,所以相当于在WHERE子句中引用的别名不存在,所以执行器提示在WHERE子句中有未知列。

  • 实现:如果一定要在WHERE子句中引用别名的话,可以使用子查询(或者说内联视图)实现。
SELECT *
FROM (SELECT eName AS employee_name,
             sal   AS salary,
             comm  AS commission
      FROM emp) t
WHERE salary < 5000;
  • 解释:当然你也许会说直接在WHERE子句中引用原始列sal或者comm不就行了么,何必多此一举。Yes, you're right! 我们这里主要想要说明的是不能在WHERE子句中引用列别名这一关键要点。

字符串连接:将多列的值合并为一列输出

  • 问题:假设你希望将多个列中的值合并为一列返回。例如,希望通过对员工表的查询生成下面这样的结果集:
  • 实现:使用你当前DBMS提供的内置函数可以实现多列值的连接操作,比如,MySQL
SELECT CONCAT(eName, ' WORK AS ', job) AS message
FROM emp
WHERE deptNo = 10;
  • 解释:使用CONCAT函数可以连接多个列的值。在DB2、Oracle和PostgreSQL中,可以用“||”代替CONCAT函数,而在SQL Server中,则用“+”。

在 SELECT 语句中使用条件逻辑

  • 问题:也许你想在SELECT语句中实现‘if-else’操作。比如,根据薪水的值对其打一个标记,不超过2000美金,标记为“UNDERPAID”;不低于4000美金则标记为“OVERPAID”;介于二者之间则标记为“OK”。
  • 实现:在SQL中,我们可以通过CASE语句实现条件逻辑
SELECT eName,
       sal,
       CASE
           WHEN sal <= 2000 THEN 'UNDERPAID'
           WHEN sal >= 4000 THEN 'OVERPAID'
           ELSE 'OK'
           END AS status
FROM emp;
  • 解释:CASE表达式允许根据查询返回的值执行条件逻辑。你可以为CASE表达式提供别名,从而返回更具可读性的结果集。在上面的实现方案中,我给CASE表达式的结果提供别名status。ELSE子句是可选的。省略ELSE,则CASE表达式将对任何不满足测试条件的行返回NULL。

限制返回行的数量

  • 问题:也许你想限制查询返回的结果行数,你并不关心顺序,任意n行即可。
  • 实现:不同的DBMS有不同的实现方式,比如MySQL或PostgreSQL就是通过LIMIT关键字实现。
SELECT *
FROM emp
LIMIT 5;

其他DBMS的实现方式如下:

-- DB2
SELECT *
FROM emp FETCH FIRST 5 ROWS ONLY;

-- Oracle
SELECT *
FROM emp
WHERE rownum <= 5;

-- SQL Server
SELECT TOP 5 *
FROM emp;
  • 解释:根据自己所使用的DBMS选择正确的实现即可,特别需要注意的是Oracle的实现中一定是rownum <= n,而不能是rownum = n。

返回n条随机记录

  • 问题:你希望从表中返回特定数量的随机记录。比如,修改下面的语句,以便连续执行产生一个由五行组成结果集:
SELECT eName, job
FROM emp;

该如何实现呢?

  • 实现:同样地,针对不同的DBMS,有不同的实现方式。使用DBMS支持的任何内置函数来返回随机值。在ORDER BY子句中使用该函数对行进行随机排序。然后,使用先前的方法来限制返回行数量即可。比如,MySQL:
SELECT *
FROM emp
ORDER BY RAND()
LIMIT 5;

如果你使用的数据库管理系统不是MySQL,请参考下面实现:

-- DB2
SELECT *
FROM emp
ORDER BY RAND()
FETCH FIRST 5 ROWS ONLY;

-- PostgreSQL
SELECT *
FROM emp
ORDER BY RANDOM()
LIMIT 5;

-- Oracle
SELECT *
FROM (SELECT *
      FROM emp
      ORDER BY dbms_random.value()) t
WHERE rownum <= 5;

-- SQL Server
SELECT TOP 5 *
FROM emp
ORDER BY newid();
  • 解释:ORDER BY子句可以接受函数的返回值并使用它来更改结果集的顺序。上面这些实现方案都限制了在ORDER BY子句中的函数执行后返回的行数。⚠需要注意的是,不要将在ORDER BY子句中使用函数和使用数字常量相互混淆。当在ORDER BY子句中指定数字常量时,指的是根据SELECT列表中相应位置的列进行排序。而在ORDER BY子句中指定一个函数时, 指的是在对每一行求值时对函数的结果执行排序。

找出具有空值的所有行

  • 问题:假设你想找出某个特定列包含空值的所有行。
  • 实现:使用IS NULL即可。
SELECT *
FROM emp
WHERE comm IS NULL;
  • 解释:NULL并不表示等于/不等于任何东西,甚至不等于它本身;因此,不能使用=或!=来测试列是否为NULL。要确定一行是否有NULL值,必须使用IS NULL。类似地,你可以使用IS NOT NULL来查找给定列中没有NULL的行 。

空值替换

  • 问题:假设你知道表中有空值,并且想将空值替换为非空值并返回。该如何实现呢?
  • 实现:出于代码的可移植性考虑,可以使用对所有DBMS都适用的COALESCE函数即可实现。
SELECT eName, sal, COALESCE(comm, 0) AS commission
FROM emp;
  • 解释:当然,对于空值替换,每个DBMS也有自己特有的函数。比如,MySQL的IFNULL(column_name, replace_value),或者SQL Server的ISNULL(column_name, replace_value)。此外,CASE表达式也可以实现,并且对所有DBMS都适用:
SELECT eName,
       sal,
       CASE
           WHEN comm IS NOT NULL THEN comm
           ELSE 0
           END AS commission
FROM emp;

当然,与CASE表达式相比,你会发现使用COALESCE函数更简单且更简洁。

搜索模式

  • 问题:假设你想要返回匹配特定子串或模式的行。考虑下面的查询和结果集:
SELECT *
FROM emp
WHERE deptNo IN (10, 20);

对于部门号为10和20的员工,如果你只想返回那些名字中含有字母“I”或职位以“ER”结尾的行,该如何实现呢?

  • 实现:使用LIKE关键字结合通配符“%”即可实现。
SELECT *
FROM emp
WHERE deptNo IN (10, 20)
  AND (eName LIKE '%I%' OR job LIKE '%ER');
  • 解释:当在LIKE模式匹配操作中使用时,百分比(%)操作符匹配任意数量的字符序列。大多数SQL实现还提供下划线(“_”) 操作符来匹配单个字符。

结论

以上所讲的各种数据检索方法和技术可能很简单,但它们却是最基本的。信息检索是数据库查询的核心,这意味着这些也将是我们后续教程所讲技术的关键核心。所以,如果可以的话,墙裂推荐跟着教程动手实践一遍。

🎗️示例数据获取:教程所用到的表及示例数据我已经整理好,关注我并回复关键字“sql教程示例数据”即可获取。

如果你觉得这篇文章对你有用,请“点赞➕在看➕分享➕关注”支持我(关注我,不迷路🤭🤭🤭),你的点赞和关注就是我持续创作分享的动力,让更多的朋友发现并加入我们,共同学习和进步!

Thank you for reading!

- END -


推荐阅读👇👇👇

2024年数据分析师都应该知道的5个高级SQL概念

13个SQL语句:解决90%的数据科学问题!你都知道哪些?

2024年SQL从新手到高手学习路线:附学习资源(赶紧收藏~~)

面试官问:SQL都有哪些类型?你怎么回答?

原文作者:数据派探险家;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2017-12-19

  • 博文量
    119
  • 访问量
    55970