T-SQL查询进阶--数据集之间的运算

上传人:飞*** 文档编号:39839786 上传时间:2018-05-20 格式:DOCX 页数:72 大小:1.78MB
返回 下载 相关 举报
T-SQL查询进阶--数据集之间的运算_第1页
第1页 / 共72页
T-SQL查询进阶--数据集之间的运算_第2页
第2页 / 共72页
T-SQL查询进阶--数据集之间的运算_第3页
第3页 / 共72页
T-SQL查询进阶--数据集之间的运算_第4页
第4页 / 共72页
T-SQL查询进阶--数据集之间的运算_第5页
第5页 / 共72页
点击查看更多>>
资源描述

《T-SQL查询进阶--数据集之间的运算》由会员分享,可在线阅读,更多相关《T-SQL查询进阶--数据集之间的运算(72页珍藏版)》请在金锄头文库上搜索。

1、简介简介数据库范式在数据库设计中的地位一直很暧昧,教科书中对于数据库范式倒是都给出了学术性的定义,但实际应用中范式的应用却不甚乐观,这篇文章会用简单的语言和一个简单的数据库 DEMO 将一个不符合范式的数据库一步步从第一范式实现到第四范式。范式的目标范式的目标应用数据库范式可以带来许多好处,但是最重要的好处归结为三点:1.减少数据冗余(这是最主要的好处,其他好处都是由此而附带的)2.消除异常(插入异常,更新异常,删除异常)3.让数据组织的更加和谐但剑是双刃的,应用数据库范式同样也会带来弊端,这会在文章后面说到。什么是范式什么是范式简单的说,范式是为了消除重复数据减少冗余数据,从而让数据库内的数

2、据更好的组织,让磁盘空间得到更有效利用的一种标准化标准,满足高等级的范式的先决条件是满足低等级范式。(比如满足 2nf一定满足 1nf)DEMO让我们先从一个未经范式化的表看起,表如下:先对表做一个简单说明,employeeId 是员工 id,departmentName 是部门名称,job 代表岗位,jobDescription 是岗位说明,skill 是员工技能,departmentDescription 是部门说明,address 是员工住址对表进行第一范式对表进行第一范式(1NF)如果一个关系模式R的所有属性都是不可分的基本数据项,则R1NF。简单的说,第一范式就是每一个属性都不可再分

3、。不符合第一范式则不能称为关系数据库。对于上表,不难看出 Address 是可以再分的,比如”北京市 XX 路 XX 小区 XX 号”,着显然不符合第一范式,对其应用第一范式则需要将此属性分解到另一个表,如下:对表进行第二范式对表进行第二范式(2NF)若关系模式R1NF,并且每一个非主属性都完全函数依赖于R的码,则R2NF简单的说,是表中的属性必须完全依赖于全部主键,而不是部分主键.所以只有一个主键的表如果符合第一范式,那一定是第二范式。这样做的目的是进一步减少插入异常和更新异常。在上表中,departmentDescription 是由主键 DepartmentName 所决定,但却不是由主

4、键 EmployeeID 决定,所以 departmentDescription 只依赖于两个主键中的一个,故要 departmentDescription 对主键是部分依赖,对其应用第二范式如下表:对表进行第三范式对表进行第三范式(3NF)关系模式R Y), 使得XY,YZ,成立,则称R中若不存在这样的码X、属性组Y及非主属性Z(Z 3NF。简单的说,第三范式是为了消除数据库中关键字之间的依赖关系,在上面经过第二范式化的表中,可以看出 jobDescription(岗位职责)是由 job(岗位)所决定,则 jobDescription 依赖于 job,可以看出这不符合第三范式,对表进行第三范

5、式后的关系图为:上表中,已经不存在数据库属性互相依赖的问题,所以符合第三范式对表进行对表进行 BC 范式范式(BCNF)设关系模式R1NF,如果对于R的每个函数依赖XY,若Y不属于X,则X必含有候选码,那么RBCNF。简单的说,bc 范式是在第三范式的基础上的一种特殊情况,既每个表中只有一个候选键(在一个数据库中每行的值都不相同,则可称为候选键),在上面第三范式的 noNf 表中可以看出,每一个员工的 email都是唯一的(难道两个人用同一个 email?)则,此表不符合 bc 范式,对其进行 bc 范式化后的关系图为:对表进行第四范式对表进行第四范式(4NF)关系模式R1NF,如果对于R的每

6、个非平凡多值依赖XY(Y X),X都含有候选码,则R4NF。简单的说,第四范式是消除表中的多值依赖,也就是说可以减少维护数据一致性的工作。对于上面 bc 范式化的表中,对于员工的 skill,两个可能的值是”C#,sql,javascript”和“C#,UML,Ruby”,可以看出,这个数据库属性存在多个值,这就可能造成数据库内容不一致的问题,比如第一个值写的是”C#”,而第二个值写的是”C#.net”,解决办法是将多值属性放入一个新表,则第四范式化后的关系图如下:而对于 skill 表则可能的值为:总结总结上面对于数据库范式进行分解的过程中不难看出,应用的范式登记越高,则表越多。表多会带来很

7、多问题:1 查询时要连接多个表,增加了查询的复杂度2 查询时需要连接多个表,降低了数据库查询性能而现在的情况,磁盘空间成本基本可以忽略不计,所以数据冗余所造成的问题也并不是应用数据库范式的理由。因此,并不是应用的范式越高越好,要看实际情况而定。第三范式已经很大程度上减少了数据冗余,并且减少了造成插入异常,更新异常,和删除异常了。我个人观点认为,大多数情况应用到第三范式已经足够,在一定情况下第二范式也是可以的。由于本人对数据库研究还处于初级阶段,所以上述如有不当之处,还望高手不吝指教SQL 查询入门查询入门(上篇上篇) 引言引言SQL 语言是一门简单易学却又功能强大的语言,它能让你快速上手并写出

8、比较复杂的查询语句。但对于大多数开发者来说,使用 SQL 查询数据库并没有一个抽象的过程和一个合理的步骤,这很可能会使在写一些特定的 SQL 查询语句来解决特定问题时被”卡”住,本系列文章主要讲述 SQL 查询时一些基本的理论,以及写查询语句的抽象思路。SQL 查询简介查询简介SQL 语言起源于 1970 年 E.J.Codd 发表的关系数据库理论,所以 SQL 是为关系数据库服务的。而对于 SQL 查询,是指从数据库中取得数据的子集是指从数据库中取得数据的子集,这句话貌似听着有些晦涩是吧,下面通过几张图片简单说明一下:假如一个数据库中只有一个表,再假如所有数据如下图(取自 Adventure

9、Work 示例数据库):而对于子集的概念,look 下图:最后,子集如下:其实,SQL 中无论多复杂的查询,都可以抽象成如上面的过程.精确查询的前置条件精确查询的前置条件对于正确取得所需要的数据子集.除了需要思路正确并将思路正确转变为对应 SQL 查询语句之外。还有很重要的一点是需要数据库有着良好的设计数据库有着良好的设计.这里的良好设计我所指的是数据库的设计符合业务逻辑并至少实现第三范式第三范式,对于实现第三范式,这只是我个人观点,对于范式的简单介绍,请看我的博客:数据库范式那些事.如果数据库设计很糟糕,存在很多冗余,数据库中信息存在大量异常,则即使 SQL 写的正确,也无法取得精确的结果。

10、两种方式,同一种结果两种方式,同一种结果在 SQL 中,取得相同的数据子集可以用不同的思路或不同的 SQL 语句,因为 SQL 源于关系数据库理论,而关系数据库理论又源于数学,思考如何构建查询语句时,都可以抽象为两种方法:1.关系代数法关系代数法关系代数法的思路是对数据库进行分步操作,最后取得想要的结果.比如如下语句:Select Name,Department,Age From Employee where Age20关系代数的思路描述上面语句为:对表 Employee 表进行投影(选择列)操作,然后对结果进行筛选,只取得年龄大于 20 的结果.2.关系演算法关系演算法相比较关系代数法而言,

11、关系演算法更多关注的是取得数据所满足的条件.上面 SQL 可以用关系演算法被描述为:我想得到所有年龄大于 20 的员工的姓名,部门和年龄。为什么需要两种方法为什么需要两种方法对于简单的查询语句来说,上面两种方法都不需要.用脚就可以想出来了。问题在于很多查询语句都会非常复杂。对于关系演算法来说更多的是关注的是所取出信息所满足的条件,而对于关系代数法来说,更多关注的是如何取出特定的信息.简单的说,关系演算法表示的是”what”,而关系代数法表达的是”how”.SQL 语句中所透漏的思路,有些时候是关系代数法,有些时候是关系演算法,还有些是两种思路的混合.对于某些查询情况,关系代数法可能会更简单,而

12、对于另外一些情况,关系演算法则会显得更直接.还有一些情况.我们需要混合两种思路。所以这两种思维方式在写 SQL 查询时都是必须的.单表查询单表查询单表查询是所有查询的中间状态,既是多个表的复杂查询在最终进行这种连接后都能够被抽象成单表查询。所以先从单表查询开始。选择列的子集选择列的子集根据上面数据子集的说法,选择列是通过在 select 语句后面添加所要选择的列名实现的:比如下面数据库中通过在 select 后面选择相应的列名实现选择列的子集列的子集.相应 sql 语句如下:SELECT Name,GroupNameFROM AdventureWorks.HumanResources.Depa

13、rtment选择行的子集选择行的子集选择行的子集是在 Sql 语句的 where 子句后面加上相应的限制条件,当 where 子句后面的表达式为“真”时,也就是满足所谓的“条件”时,相应的行的子集行的子集被返回。where 子句后面的运算符分为两类,分别是比较运算符比较运算符和逻辑运算符逻辑运算符.比较运算符是将两个相同类型的数据进行比较,进而返回布尔类型(bool)的运算符,在 SQL 中,比较运算符一共有六种,分别为等于(=),小于(),小于或等于(=)以及不等于(1 and DepartmentID5 and DepartmentID于(And)非(Or)当然,运算符也可以通过小括号来改

14、变优先级,对于上面那个表对于不加括号时:SELECT *FROM AdventureWorks.HumanResources.DepartmentWHERE DepartmentID=1 and DepartmentID=5 or DepartmentID=1 and DepartmentID=5 or DepartmentID(大于) 、=(大于或等于) 、(不大于) 、!(不等于) 。当然,限制条件所涉及的两个列的数据类型数据类型必须匹配.对于上面的查询语句,如果将 on 后面限制条件由等于改为大于:SELECT *FROM Class cinner join Student son c.

15、ClassIDs.StudentClassID则结果从第一步的笛卡尔积中筛选出那些 ClassID 大于 StudentClassID 的子集子集:虽然上面连接后的表并没有什么实际意义,但这里仅仅作为 DEMO 使用:-)关系演算关系演算上面笛卡尔积的概念是关系代数中的概念,而我在前一篇文章中提到还有关系演算的查询方法.上面的关系代数是分布理解的,上面的语句推导过程是这样的:“对表 Student 和 Class 进行内连接,匹配所有 ClassID 和 StudentClassID 相等行,选择所有的列”而关系演算法关系演算法,更多关注的是我想要什么我想要什么,比如说上面同样查询,用关系演算

16、法思考的方式是“给我找到所有学生的信息,包括他们的班级信息,班级 ID,学生 ID,学生姓名”用关系演算法的 SQL 查询语句如下:SELECT *FROM Class c,Student swhere c.ClassID=s.StudentClassID当然,查询后返回的结果是不会变的:外连接外连接假设还是上面两个表,学生和班级.我在学生中添加一个名为 Eric 的学生,但出于某种原因忘了填写它的班级 ID:当我想执行这样一条查询:给我取得所有学生的姓名和他们所属的班级:SELECT s.StudentName,c.ClassName FROM fordemo.dbo.Student sinner join fordemo.dbo.Class con s.StudentClassID=c.ClassID结果如下图:可以看到,这个查询“丢失”了 Eric.这时就需要用到外连接,外连接可以使连接表的一方,或者双方不必遵守 on 后面的连接限制条件.这里把上

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 商业/管理/HR > 其它文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号