SQL语言是一门简单易学却又功能强大的语言,它能让你快速上手并写出比较复杂的查询语句。但对于大多数开发者来说,使用SQL查询数据库并没有一个抽象的过程和一个合理的步骤,这很可能会使在写一些特定的SQL查询语句来解决特定问题时被”卡”住,本系列文章主要讲述SQL查询时一些基本的理论,以及写查询语句的抽象思路。

SQL查询简介

SQL语言起源于1970年E.J.Codd发表的关系数据库理论,所以SQL是为关系数据库服务的。而对于SQL查询,是指从数据库中取得数据的子集,这句话貌似听着有些晦涩是吧,下面通过几张图片简单说明一下:

假如一个数据库中只有一个表,再假如所有数据如下图(取自AdventureWork示例数据库):

而对于子集的概念,look下图:

最后,子集如下:

其实,SQL中无论多复杂的查询,都可以抽象成如上面的过程.

精确查询的前置条件

对于正确取得所需要的数据子集.除了需要思路正确并将思路正确转变为对应SQL查询语句之外。还有很重要的一点是需要数据库有着良好的设计.这里的良好设计我所指的是数据库的设计符合业务逻辑并至少实现第三范式,对于实现第三范式,这只是我个人观点,对于范式的简单介绍,请看我的博客:数据库范式那些事.如果数据库设计很糟糕,存在很多冗余,数据库中信息存在大量异常,则即使SQL写的正确,也无法取得精确的结果。

两种方式,同一种结果

在SQL中,取得相同的数据子集可以用不同的思路或不同的SQL语句,因为SQL源于关系数据库理论,而关系数据库理论又源于数学,思考如何构建查询语句时,都可以抽象为两种方法:

1.关系代数法

关系代数法的思路是对数据库进行分步操作,最后取得想要的结果.

比如如下语句:

Select Name,Department,Age
From Employee
where Age>20

关系代数的思路描述上面语句为:对表Employee表进行投影(选择列)操作,然后对结果进行筛选,只取得年龄大于20的结果.

2.关系演算法

相比较关系代数法而言,关系演算法更多关注的是取得数据所满足的条件.上面SQL可以用关系演算法被描述为:我想得到所有年龄大于20的员工的姓名,部门和年龄。

为什么需要两种方法

对于简单的查询语句来说,上面两种方法都不需要.用脚就可以想出来了。问题在于很多查询语句都会非常复杂。对于关系演算法来说更多的是关注的是所取出信息所满足的条件,而对于关系代数法来说,更多关注的是如何取出特定的信息.简单的说,关系演算法表示的是”what”,而关系代数法表达的是”how”.SQL语句中所透漏的思路,有些时候是关系代数法,有些时候是关系演算法,还有些是两种思路的混合.

对于某些查询情况,关系代数法可能会更简单,而对于另外一些情况,关系演算法则会显得更直接.还有一些情况.我们需要混合两种思路。所以这两种思维方式在写SQL查询时都是必须的.

单表查询

单表查询是所有查询的中间状态,既是多个表的复杂查询在最终进行这种连接后都能够被抽象成单表查询。所以先从单表查询开始。

选择列的子集

根据上面数据子集的说法,选择列是通过在select语句后面添加所要选择的列名实现的:

比如下面数据库中通过在select后面选择相应的列名实现选择列的子集.

相应sql语句如下:

SELECT [Name],[GroupName]FROM [AdventureWorks].[HumanResources].[Department]

选择行的子集

选择行的子集是在Sql语句的where子句后面加上相应的限制条件,当where子句后面的表达式为“真”时,也就是满足所谓的“条件”时,相应的行的子集被返回。

where子句后面的运算符分为两类,分别是比较运算符和逻辑运算符.

比较运算符是将两个相同类型的数据进行比较,进而返回布尔类型(bool)的运算符,在SQL中,比较运算符一共有六种,分别为等于(=),小于(<),大于(>),小于或等于(<=),大于或等于(>=)以及不等于(<>),其中小于或等于和大于或等于可以看成是比较运算符和逻辑运算符的结合体。

而逻辑运算符是将两个布尔类型进行连接,并返回一个新的布尔类型的运算符,在SQL中,逻辑运算符通常是将比较运算符返回的布尔类型相连接以最终确定where子句后面满足条件的真假。逻辑运算符一种有三种,与(AND),或(OR),非(NOT).

比如上面,我想选择第二条和第六条,为了说明比较运算符和逻辑运算符,可以使用如下Sql语句:

SELECT [Name],[GroupName]FROM [AdventureWorks].[HumanResources].[Department]WHERE DepartmentID>1 and DepartmentID<3 or DepartmentID>5 and DepartmentID<7

由此我们可以看出,这几种运算符是有优先级的,优先级由大到小排列是比较运算符>于(And)>非(Or)

当然,运算符也可以通过小括号来改变优先级,对于上面那个表

对于不加括号时:

SELECT *FROM [AdventureWorks].[HumanResources].[Department]WHERE DepartmentID>=1 and DepartmentID<=3 and DepartmentID>=5 or DepartmentID<=7

加了括号改变运算顺序后:

SELECT *FROM [AdventureWorks].[HumanResources].[Department]WHERE DepartmentID>=1 and DepartmentID<=3 and (DepartmentID>=5 or DepartmentID<=7)

很特别的NULL

假如在一个用户注册的表中,一些选填信息并不需要用户必须填写,则在数据库中保存为null,这些null值在利用上面where子句后的运算符时,有可能造成数据丢失,比如一个选填信息是性别(Gender),假设下面两条条件子句:

where Gender="M"
where NOT (Gender="M")

由于null值的存在,这两条语句返回的数据行加起来并不是整个表中的所有数据。所以,当将null值考虑在内时,where后面的条件子句拥有可能的值从真和假,增加为真,假,以及未知(null)。这些是我们在现实世界中想一些问题的时候可能的答案--真的,假的,我不知道。

所以我们如何在这种情况下不丢失数据呢,对于上面的例子来说,如何才能让整个表的数据不被丢失呢,这里必须将除了“真”,“假”以外的“未知”这个选项包含在内,SQL提供了IS NULL来表明未知这个选项:

where Gender IS NULL

将上面语句加入进去,则不会再丢失数据。

排序结果

上面的那些方法都是关于取出数据,而下面是关于将取出的子集进行排序。SQL通过Order by子句来进行排序,Order by子句是Sql查询语句的最后一个子句,也就是说Order by子句之后不能再加任何的子句了。

Order By子句分为升序(ASC)和降序(DESC),如果不指定升序或者降序,则默认为升序(由小到大),而Order by是根据排序依据的数据类型决定,分别为3种数据类型可以进行排序:

  1. 字符
  2. 数字
  3. 时间日期

字符按照字母表进行排序,数字根据数字大小排序,时间日期根据时间的先后进行排序。

其它一些有关的

视图

视图可以看作是一个保存的虚拟表,也可以简单看做是保存的一个查询语句。视图的好处是视图可以根据视图所查询表的内容的改变而改变,打个比方来理解这句话是:

使用视图的优点是可以对查询进行加密以及便于管理,据说还可以优化性能(我不认可这点).

防止重复

有时候我们对于取出的数据子集不想重复,比如你想知道一些特定的员工一共属于几个部门

SELECT [EmployeeID],[DepartmentID]FROM [AdventureWorks].[HumanResources].[EmployeeDepartmentHistory]

这样的结果是没有意义的,SQL提供了Distinct关键字来实现这点:

SELECT distinct DepartmentIDFROM [AdventureWorks].[HumanResources].[EmployeeDepartmentHistory]

聚合函数

所谓聚合函数,是为了一些特定目的,将同一列多个值聚合为一个,比如我想知道一群人中最大年龄是多少可以利用MAX(Age),比如我想知道一个班级平均测验成绩是多少可以用AVG(Result)……

总结

文章简单概述了SQL查询的原理以及简单的单表查询,这些都是数据库查询的基础概念,对于进行复杂查询来说,弄明白这些概念是必不可少的。

SQL查询入门(上篇)相关推荐

  1. SQL查询入门(中篇)

    引言 在前篇文章中(SQL查询入门(上篇),我对数据库查询的基本概念以及单表查询做了详细的解释,本篇文章中,主要说明SQL中的各种连接以及使用范围,以及更进一步的解释关系代数法和关系演算法对在同一条查 ...

  2. SQL查询入门(下篇)

    引言 在前两篇文章中,对于单表查询和多表查询的概念做出了详细的介绍,在本篇文章中会主要介绍聚合函数的使用和数据的分组. 简介 简单的说,聚合函数是按照一定的规则将多行(Row)数据汇总成一行的函数.对 ...

  3. sql server 入门_SQL Server查询调整入门

    sql server 入门 This article will cover some essential techniques for SQL query tuning. Query tuning i ...

  4. 「SQL数据分析系列」3.查询入门

    来源 |  Learning SQL Generate, Manipulate, and Retrieve Data, Third Edition 作者 | Alan Beaulieu 译者 | Li ...

  5. vba ado 执行多条mysql 语句,Excel VBA+ADO+SQL入门教程003:SQL查询中字段技巧的总结...

    原标题:Excel VBA+ADO+SQL入门教程003:SQL查询中字段技巧的总结 本章概要: 1,几个概念 1.1, 数据库和Excel工作簿 1.2,数据表和Excel工作表 1.3,记录.字段 ...

  6. 教学思路SQL之入门习题《学生成绩》 五、使用视图完成多表查询

    视图的概念: 视图对象是一个虚拟的表,虚拟表所包含的结果集是对一个或多个表的查询. 视图本身不保存这个结果集,而是保存查询的定义. 视图的定义是对已经存在表的查询. 使用视图和使用表很类似,可以把视图 ...

  7. 【数据库】SQL极速入门(多种方式查询用户复借次数)

      最近遇到这样一个事:许多DBA的小伙伴不太明白金融业务中复借用户的定义方式以及sql查询方式,给他们提需求也整不明白,需求如下:   根据订单编号,查询用户该订单所对应的复借次数(白话讲就是:我有 ...

  8. SQL轻松入门(1):增删改与简单查询

    作者介绍 ​鲸歌 电商行业数据分析师 为头部品牌提供数据咨询服务 热衷学习与分享 "数据人创作者联盟"成员 在下笔写SQL系列文章时,我突然有点懵,因为从某种意义上来说SQL是我熟 ...

  9. sql 找到最近的值_数据分析——SQL查询(常用函数)

    SQL入门推荐书籍--<SQL必知必会>.猴子的live课程--<从零开始学SQL> [基本SQL查询语句] select 选择输出字段 from 摘自某表 as 取别名(如果 ...

最新文章

  1. python mixup
  2. python怎么实现数据可视化_数据之美,python实现数据可视化!
  3. 时间序列分析 pdf_多变量时间序列的聚类分析与相似查询——多变量时间序列的相似查询分析...
  4. 怎么画单极交流放大电路波形图_区别在哪?:VCC、VDD、VEE、VSS、数字地、模拟地、信号地、交流地、直流地!...
  5. Orchard源码分析(5.3):EndRequest事件处理(DefaultOrchardHost.EndRequest方法)
  6. 盖茨买下一座城,想建成沙漠中的智慧城市
  7. 【李宏毅2020 ML/DL】P20-21 Recurrent Neural Network | “Deep and structure is future.“
  8. jQuery命令汇总(转)
  9. 计算机实战项目之 [含论文+任务书+中期检查表+答辩PPT+源码等]基于javaweb大学生助学贷款管理系统
  10. 大牛熬夜整理,京东网易滴滴,天津农行软开java面试题合集,大牛已于上个月入职华为!
  11. 电池管理系统(BMS)
  12. FPGA之JESD204B接口——总体概要 首片
  13. Word:文档中如何批量删除参考文献的引文格式[1]、[2]...
  14. 计算机硬盘显示offline,LSI芯片Raid卡一块硬盘显示红色Offline(或者Failed)
  15. RabbitMQ安装过程(Win10)
  16. 超几何分布HyperGeometricDistribution
  17. 用turtle画奥运五环
  18. Mac conda 使用
  19. xp系统怎样启动搜索服务器,XP系统使用搜索功能的三种方式
  20. 多元线性回归的基础理解

热门文章

  1. 【Android 插件化】VirtualApp 源码分析 ( 目前的 API 现状 | 安装应用源码分析 | 安装按钮执行的操作 | 返回到 HomeActivity 执行的操作 )
  2. 【SeeMusic】视频编辑 ( 顶部裁剪 | 底部裁剪 | 左侧裁剪 | 右侧裁剪 | 明亮度 | 对比度 | 色调 | 饱和度 )
  3. 【数据挖掘】数据挖掘总结 ( 拉普拉斯修正 | 贝叶斯分类器示例2 ) ★
  4. 【Android 应用开发】 Android 相关代码规范 更新中 ...
  5. 一个操作读写已存在excel 文件的例子
  6. Java时间和时间戳的相互转换
  7. 2.2.5 NIO.2 Path 和 Java 已有的 File 类
  8. PHP 将二叉查找树转换为双向链表,要求不能创建新节点,只能调节节点指针
  9. 函数式编程与REST的思考
  10. C#几种常用的排序算法