原文:被忽视但很实用的那部分SQL

一、前言

虽然我们大多数人都学习过SQL,但是经常忽略它。总是会自以为学到的已经足够用了,从而导致我们在实际开发的过程中遇到复杂的问题后只能在检索数据后通过传统的代码来完成,但是其中很多的功能利用SQL就可以轻松的办到,所以我们开始重视SQL,它的地位不亚于C#javascript

二、目录

1.多行插入

2.将其他表数据插入

3.子查询

4.通用表表达式(CTE)

5.MERGE指令

6.窗口化函数

7.查询分页

三、正文

1.多行插入

大家都学习过INSERT,但是每次我们都只插入一条数据,如果我们需要插入多条数据呢,那么情况就会和图1.1一样。

图1.1

上面是最简单的示例,我们还可以进行一定的优化,避免循环建立和关闭连接的次数,比如下图(图1.2

图1.2

即使我们采用了图1.2所示的方式,既然会长时间的占据带框,并且Web服务器和数据库服务器既然要进行多次连接,如果使用本节的知识我们就可以做到图1.3所示的效果。

图1.3

首先我们先来看看普通的插入语句:

1 INSERT INTO Cou_Course(CourseID,TeacherID,SemesterID,CourseName,CourseType,CourseState)
2 VALUES('235648651235423512','12312421421','12124214124','awefweagwaeg','123','124124')

每次插入一条新的数据都要重新一次,如果是批量的添加就可想而知了,而如果我们直接通过一条插入语句插入多条数据就可以这样做:

1 INSERT INTO Cou_Course(CourseID,TeacherID,SemesterID,CourseName,CourseType,CourseState)
2 VALUES('235648651235423515','12312421421','12124214124','awefweagwaeg','123','124124'), 3 ('235648651235423514','12312421421','12124214124','awefweagwaeg','123','124124'), 4 ('235648651235423517','12312421421','12124214124','awefweagwaeg','123','124124')

当然语法也很简单,只要用逗号来分割就可以了。虽然仅仅只是一个简单的技巧,但是又有多少人会使用呢?

2.将其他表数据插入

解决了批量插入的问题,我们还会遇到将其他表的数据插入到另一个表中的需求,特别是在编写存储过程中我们可能会对数据进行处理,并把处理的结果存放在临时 表中,最后才将临时表中的数据全部添加到实际的表中,如果利用传统的做法会非常麻烦,而通过本节介绍的知识将可以很轻松的实现。

首先我们需要做一些简单的准备工作,这里我们需要创建两个表,A表(id为自增),B表跟A表一样,然后我们在A表中随意写一些内容:

然后利用 INSERT INTOSELECT … 来实现将A表的数据添加到B表中去:

INSERT INTO B(Name) SELECT Name FROM A

当然读者看过之后会觉得非常简单,因为我们现在仅仅只是学习这个知识点,重点在于我们能够记住它,并能够在后面使用它(实际开发中会比这更复杂,但是基本的东西还是不变的)

3.子查询

在正常的使用中我们经常会遇到无法使用链接的情况,但是我们需要根据另一个表的情况来决定当前的SELECT,这个时候我们就需要子查询。笔者在这里只能例举简单的示例,实际的需求会出现非常复杂的子查询。这里我们还是借助上面的A、B表,首先实现的功能是检索A表,但是条件是A表的Name要在B表中存在:

SELECT id,Name FROM A
WHERE EXISTS( SELECT Name FROM B WHERE B.Name = A.Name )

上面的语句中我们在WHERE中就使用了子查询负责去B表中查询是否存在记录,而EXISTS的作用就是EXISTS括号中的语句只要返回了一个或一个以上的结果则成立。所以最后我们可以看到所有的数据都呈现了。当然子查询不仅仅可以用于条件中,我们还可以用于SELECT后,比如我们根据A表的Name去B表中查询Name跟它一样的id号:

SELECT (SELECT TOP 1 B.id FROM B WHERE B.Name = A.Name) FROM A

子查询的用处非常多,也非常强大,远不止笔者这里介绍的这么一点。

4.通用表表达式(CTE)

虽然这个名字很专业,但是实际用起来是非常简单的,当然简单的同时也帮助我们解决了很多的问题,最终的效果跟临时表一样,但是使用起来比临时表更方便。比如下面的代码我们将创建一个名为MyCTE的临时表:

WITH MyCTE AS(SELECT * FROM A ) SELECT * FROM MyCTE

是不是非常简单,当然还可以同时定义多个通用表,比如下面的代码所示:

1 WITH MyCTE AS(
2   SELECT * FROM A 3 ), MyCTE2 AS( 4 SELECT * FROM B 5 ) 6 SELECT * FROM MyCTE,MyCTE2

多个通用表只需要用逗号分割即可,当然我们这里还涉及了一个知识点,相信有人会发觉出来。

5.MERGE指令

这个指令是SQL SERVER 2008中 新增的,相比前面几个来说比较难懂,但是作用却非常强大,利用这个指令我们可以同时进行添加、修改和删除,并且是由条件的。具体的实现方式就是根据源表与 目标表进行对比,如果匹配则执行对应的更新操作,如果源表中存在,但是目标表不存在则执行添加操作,如果相反则执行删除操作。下面我们将通过循序渐进的方 式来介绍如何使用MERGE,首先我们需要确定目标表,因为后面的更新,添加和删除操作都是针对目标表的,所以目标表只能是一个表不能是检索后的数据,比如下面的代码我们将前面我们示例中使用的A表作为目标表:

1 MERGE A AS itarget

有了目标表还不足够,我们还要需要一个源表,用来形成对比,而源表则可以是检索语句,因为笔者这里只是简单的示例,所以直接检索了B表中的数据:

1 USING(
2   SELECT * FROM B 3 ) AS isource

这样我们就有了目标表和源表,最后合并:

1 MERGE A AS itarget
2 USING(
3 SELECT * FROM B 4 ) AS isource

接着我们需要指定对应的条件,从而根据是否符合这个条件而决定对目标表进行什么操作,比如下面的语句将判断两表中是否存在相同id的数据:

ON (itarget.id = isource.id)

有了条件后,我们就可以根据这个条件进行对应的操作了,笔者将在满足这个条件后修改目标表的Name,在后面追加change字符串:

1 WHEN MATCHED THEN
2 UPDATE SET itarget.Name = itarget.Name + 'change'

最后的语句如下所示:

1 MERGE A AS itarget
2 USING(
3 SELECT * FROM B 4 ) AS isource 5 ON (itarget.id = isource.id) 6 WHEN MATCHED THEN 7 UPDATE SET itarget.Name = itarget.Name + 'change';

最后我们查看A表,发现数据都改变了:

这个时候我们在A表新添加一条数据,以满足源表不匹配的情况,然后在原本的语句后面添加如下的语句:

WHEN NOT MATCHED BY SOURCE THEN
DELETE;

我们可以猜测出,当目标表中存在源表中不存在的数据后将会删除这条数据,所以执行后我们将看到A表新添加的数据已经被删除了,完整的语句如下所示:

1 MERGE A AS itarget
2 USING(
3 SELECT * FROM B 4 ) AS isource 5 ON (itarget.id = isource.id) 6 WHEN MATCHED THEN 7 UPDATE SET itarget.Name = itarget.Name 8 WHEN NOT MATCHED BY SOURCE THEN 9 DELETE;

最后就是源表中存在,但是目标表中不存在的情况了,我们只需要将上面的BY SOURCE改成BY TARGET即可,通过下面这条语句我们将把源表与目标表不匹配的数据添加到目标表中去(当然我们需要提前在源表中新增一条数据)

WHEN NOT MATCHED BY TARGET THEN
INSERT (Name) VALUES(isource.Name);

执行完成后我们将看到A表多了几条数据。下面是完整的语句:

 1 MERGE A AS itarget
 2 USING(
 3 SELECT * FROM B  4 ) AS isource  5 ON (itarget.id = isource.id)  6 WHEN MATCHED THEN  7 UPDATE SET itarget.Name = itarget.Name  8 WHEN NOT MATCHED BY SOURCE THEN  9 DELETE 10 WHEN NOT MATCHED BY TARGET THEN 11 INSERT (Name) VALUES(isource.Name);

6.窗口化函数

首先是ROW_NUMBER,顾名思义,就是给我们检索出来的数据加上序号,旧的分页都是采用这种方式,但是往往我们仅仅只是使用了它的一点,他还可以分块进行标序号,比如我们将上面的A表改成如下形式:

然后采用如下所示的SQL语句,就可以按照Name进行标序号:

SELECT ROW_NUMBER() OVER(PARTITION BY A.Name ORDER BY A.id) AS 'RNUM',id FROM A

结果如下所示:

下面我们通过一段SQL以及对应的结果呈现其他的窗口化函数:

SELECT ROW_NUMBER() OVER(PARTITION BY A.Name ORDER BY A.id) AS 'RNUM', RANK() OVER(ORDER BY A.Name) AS 'RANK', DENSE_RANK() OVER(ORDER BY A.Name) AS 'DENSE RANK', NTILE(4) OVER(ORDER BY A.id) AS 'NTILE' FROM A

结果如下所示:

其中简单介绍下NTILE,我们传了一个4那么它会将前面1/4标记为1,然后接着标记1/4为2,以此类推。关于RANKDENSE_RANK比较好理解,看看最后的结果就可以得出结论了。

7.分页查询

这是最后一节了,但是相关的语句却很简单,我们只要记住以下关键字就可以了:

OFFSET…FETCH  NEXT…

比如下面的SQL语句,我们将跳过前面5条数据,获取3条数据:

1 SELECT * FROM A
2 ORDER BY A.id 3 OFFSET 5 ROWS 4 FETCH NEXT 3 ROWS ONLY

被忽视但很实用的那部分SQL相关推荐

  1. Mac系统容易忽视但很实用的命令整理

    001.终端指定用哪个软件打开指定的文件 # open -a 实用哪个软件(软件名有空格需转义) 文件名路径 open -a /Applications/Google\ Chrome.app xx.h ...

  2. 很实用的21个SQL小技巧!

    前言 每一个好习惯都是一笔财富,本文基于MySQL,分SQL后悔药, SQL性能优化,SQL规范优雅三个方向,分享写SQL的21个好习惯,谢谢阅读,加油哈~ 1. 写完SQL先explain查看执行计 ...

  3. 一个PS高手的话,对初学者很实用

    一个PS高手的话,对初学者很实用 2011年05月09日 1.不要看到别人的作品第一句话就说:给个教程吧!你应该想这个是怎么做出来的.当你自己想出来,再对照别人的教程的时候,你就知道自己和别人的思路的 ...

  4. SAP MM 盘点流程中上不了台面却很实用的方案建议

    SAP MM 盘点流程中上不了台面却很实用的方案建议 SAP项目里,往往少不了MM模块,启用了MM模块就少不了盘点流程. 业务实践中,对于盘点业务,一般作业流程是: 根据企业管理策略,确定需要盘点的物 ...

  5. 很实用但经常忘的小常识

    很实用但经常忘的小常识 1.羊肉去膻味:将萝卜块和羊肉一起下锅,半小时后取出萝卜块:放几块桔子皮更佳:每公斤羊肉放绿豆5克,煮沸10分钟后,将水和绿豆一起倒出:放半包山楂片:将带壳的核桃两三个洗净打孔 ...

  6. 中文论文万能句型_SCI 论文写作万能句型汇总(很实用)

    主要是从一下几个方面来汇总的万能句型,例如: 摘要:描述观点的重要性 One of the most significant current discussions in legal and mora ...

  7. Web 开发中很实用的10个效果【附源码下载】

    在工作中,我们可能会用到各种交互效果.而这些效果在平常翻看文章的时候碰到很多,但是一时半会又想不起来在哪,所以养成知识整理的习惯是很有必要的.这篇文章给大家推荐10个在 Web 开发中很有用的效果,记 ...

  8. Vim不常见但是很实用的命令技巧

    概述 Linux vi/vim Vim不常见但是很实用的命令技巧 命令 保存文件并退出 :x 和下面的命令是等价的: :wq 都是保存当前文件并退出. 区别:这两个命令实际上并不完全等价,当文件被修改 ...

  9. Excel电子表格的使用技巧!很实用

    电子表格的使用技巧!很实用啊! Excel高级使用技巧 1.编辑技巧 (1) 分数的输入 如果直接输入"1/5",系统会将其变为"1月5日",解决办法是:先输入 ...

最新文章

  1. 微型计算机的发展通常以为技术指标,计算机组成原理期末复习题.doc
  2. python入门教程共四本书籍-关于 Python 的经典入门书籍有哪些?
  3. .exe已停止工作_【PS课堂】你的photoshop已停止工作了,文件未保存该怎么办?
  4. 通过Dapr实现一个简单的基于.net的微服务电商系统(六)——一步一步教你如何撸Dapr之Actor服务...
  5. 第11课 尼克与强盗 《小学生C++趣味编程》
  6. Spring Security整合JWT,实现单点登录,So Easy~!
  7. CentOS6.4 Install Nginx 1.4.4 到特定目录
  8. DNS原因导致的不能访问网站问题一例
  9. excel表格如何设置双面打印的方法
  10. 宏基aspire拆机触摸_宏基(acer)Aspire 4930G拆机教程
  11. 英语时态8种基本时态讲解
  12. Android 虚拟机EditText键盘无法输入解决方法
  13. python制作u盘病毒_Python-记一次U盘中病毒及文件找回
  14. [分享]一次中移物联网校园招聘javaweb的笔试题
  15. 联想小新Air13高定黑使用初体验
  16. oh-my-zsh配置 alias 指定指令别名
  17. 强化学习算法A2C(Advantage Actor-Critic)和A3C(Asynchronous Advantage Actor-Critic)算法详解以及A2C的Pytorch实现
  18. 小学生关于计算机的知识,计算机是什么,给小学生讲计算机知识.ppt
  19. android sutdio导入源码教程,《AndroidStudio导入安卓源码-idegen》---可方便查看安卓源代码...
  20. 极路由X(C526A)刷Openwrt 18.06固件(2021-12-12亲测)

热门文章

  1. Boost:bimap双图lambda表达式的测试程序
  2. Boost:align down向下对齐的测试程序
  3. Boost:timer计时器测试程序
  4. VTK:可视化之CollisionDetection
  5. OpenCV自定义CN跟踪器
  6. C语言实现段树segment tree(附完整源码)
  7. QT的QQmlContext类的使用
  8. QT的QGLShaderProgram类的使用
  9. QT的QEnableSharedFromThis类的使用
  10. C++ Opengl纹理过滤和光照实例源码