SQL——以面向集合的思维方式来思考

本文来自:http://www.ituring.com.cn/article/details/472

  为了以有趣的方式更好地帮助你形成面向集合的思维方式,我将给出自己最喜欢的游戏之一——集合。你可以在线玩这个游戏,网址是www.setgame.com/puzzle/set.htm,每天都会贴出一个新的集合谜题。集合游戏是一个每张卡片上有4个特征的谜题:颜色、符号、底纹以及符号的个数。颜色有红、绿和紫色。符号有花体、方块以及椭圆。底纹可以是实的、斑点的及外轮廓线。至于符号个数,每张卡上可能有一个、两个或三个符号。要成为集合只有一条规则:一个集合只需要3张卡上的每一种单独的特征要么都一样要么全不相同。因此,一个有效的集合的例子就是3张卡上有相同的符号(例如方块),3张卡上都有两个符号,3张卡的颜色各不相同,并且3张卡都是实心图案。所有使得3张卡上具有相同特征或者完全不同特征的组合都能构成集合。游戏的目标就是在12张卡中寻找集合。当找到一个集合后,这3张卡片就将被去掉,并加入3张新卡片。在在线版本中,12张卡片总会有6个集合,你的目标就是要找出所有这6个集合。

  图4-1给出了12张卡片,从中你应该可以找出6个集合。每张卡片左上角的字母表示颜色(R=红色,G=绿色,P=紫色)。试试吧。

enter image description here

答案在本章的最后(可别作弊哦!)。我首先给出第一个集合:第1行第2列(实心绿色花体),第3行第2列(实心红色花体)和第3行第4列(实心紫色花体)。这个游戏迫使你按集合来思考,除此以外别无他法。如果你觉得找出集合很困难,我打赌你在写SQL语句的时候就会觉得以面向集合的方式来思考更困难。SQL语句的书写工作与这个游戏是具有同样的前提的(必须要有面向集合的思维方式!),只不过是另外一个不同的游戏罢了。既然你已经在面向集合的思考方面热过身了,让我们来看看从面向过程的思维方式转变到面向集合的思维方式的几种方法。

从面向过程转变为基于集合的思维方式

  你首先需要做的是停止那些一次处理一行数据的过程化步骤思维。如果你一次只想处理一行,实现你的想法将会使用短语如“for each row do x”或者 “while value is y do x”。试着把思路转移到使用类似于“for all”的短语上来。有关于此的一个简单的例子就是加数字。当你按过程化来考虑的时候,你就会想把一行的数值与另一行的数值加起来直到把所有行加到一起。对所有行求和的思维与此不同。正如我所说的,这是个非常简单的例子,但类似的思维方式的转变同样适用于更复杂的不是那么明显的情况下。

  例如,如果我让你生成一个所有在公司里每个工作岗位上干了同样年数的员工列表,你会怎么做?如果你按照过程化的思维方式来进行,你可能需要去查看每个工作岗位,计算出在这个岗位上的工作年限,然后与在其他各个岗位的工作年限比较。如果年数不匹配,那么你就不会把这个员工放到结果列表中。这种方法将会通过如下的一个自联结的查询来进行:

enter image description here

  相反,如果你使用面向集合的观点来看待这个问题,你就会写出对表只进行一次访问的查询,按照员工进行分组,然后筛选出那些在某个岗位上工作的最短年数与某个岗位上工作的最长年数相一致的员工。

enter image description here

  代码清单4-1分别列出了这两种选择的执行过程。你可以看到基于集合的方法使用了较少的逻辑读取并拥有更简洁的计划。

代码清单4-1 过程化与基于集合的方法的对比

enter image description hereenter image description hereenter image description here

  关键是要开始以完成后的结果的形式(而不是以处理步骤的形式)来思考。要找集合的特征而不是单独的步骤或行为。在基于集合的思维方式中,所有事物都以应用于集合的筛选条件或约束所定义的状态存在。你不再按照过程步骤来思考而是要按照集合的状态来思考。图4-2给出了处理步骤图与嵌套集合图之间的一个比较用来说明我的观点。

enter image description here

  处理流程图表明结果集(A)是通过一系列以其他步骤为基础的处理步骤来产生的最终答案。B通过遍历C和D得出,然后A通过遍历B和E得出。但是,嵌套集合图中将A看做是不同集合的组合的结果。

  另一种常见的但却是错误的思考方式就是将表看做是排过序的行的集合。想想你所看到的典型的表的内容。它们是在一个表格或者类似于工作表的视图中展示出来的。但是,一张表代表一个集合,集合是无序的。通过表明一定顺序的方法来展示表可能会引起混淆。回忆一下在第2章中ORDER BY子句是在一个SQL语句执行的最后来实现的。SQL是基于集合理论的,正因为集合中的行没有预先确定的顺序,排序就必须在符合查询条件的数据行都被从集合中抽取出来之后再单独进行。图4-3给出了一种更恰当的方法来说明表中的内容是无序的。

enter image description here

  看上去区分这些你在思考问题方式上的细小差别并不是那么重要,但是这些细小的转变是正确理解SQL的基础。让我们来看一个例子,通过面向过程的思维方式和基于集合的思维方式分别来写一个SQL语句,以帮助你弄清楚二者之间的区别。

面向过程vs.基于集合的思维方式:一个例子

   在这个例子中,任务是要计算出一个顾客在各个订单之间的平均天数。代码清单4-2给出了通过面向过程的思维方式的实现方法。为了让例子的输出较短,我将只计算一个顾客的,但是由此可以很容易地转变为计算所有顾客的。

代码清单4-2 面向过程的思维方式

enter image description here

enter image description here

  这看上去相当优雅,不是吗?在这个例子中,我依次执行了一系列查询来展示我是如何思考的,并按照逐步进行的过程方法来书写查询语句。如果你对分析函数LAG的使用方法还不是很熟悉,不必担心,分析函数将在第8章进行讲解。简单来说,我所做的事情就是按照orderdate的顺序读取102号顾客的每一行订单信息,然后使用LAG函数,回过头再看前一行的订单数据以获得该行的orderdate。当得到这两个order_date(当前订单行的日期以及前一行订单的日期)以后,利用这两个日期相减得出中间相差的天数就非常简单了。最后,我使用求平均值聚合函数来得到最终的答案。

  你可能会指出这个查询是按照非常过程化的方式建立起来的。理解这种方式最好的办法就是依次来看几个不同的查询以展示如何建立最终结果集的。在这个过程中我可以看到相关详细信息。当以基于集合的思维方式进行思考的时候,你会发现并不需要去关心每一个单独的元素。代码清单4-3给出了一个按照基于集合的思维方式来写的查询例子。

代码清单4-3 基于集合的思维方式

enter image description here

  这样怎么样?我根本不需要任何花哨的技巧来解决这个问题。我用来计算订单之间的平均天数所要做的事情就是计算出第一笔和最后一笔订单之间的天数以及总的订单数。我不需要一步一步地来考虑问题,正如我也不会写一个一行一行读取数据然后计算出结果的程序。我所需要的就是把我考虑问题的思维方式转变到将集合数据作为一个整体来考虑。

  我并不是完全无视过程化方法。可能有的时候你不得不采用这样的方法来完成工作。然而,我想鼓励你进行思维方式的转变:首先寻找基于集合的方式,只有在需要的时候才采用更大程度的过程化方法。通过这样做,你可能会发现自己可以得到更简单、直接的,通常性能也更好的解决方案。


转载于:https://www.cnblogs.com/qianqian0313/archive/2011/10/31/2394845.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/380136.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

远控免杀专题(16)-Unicorn免杀

0x01 免杀能力一览表 几点说明: 1、上表中标识 √ 说明相应杀毒软件未检测出病毒,也就是代表了Bypass。 2、为了更好的对比效果,大部分测试payload均使用msf的windows/meterperter/reverse_tcp模块生成。 3、由于本机测试时只是安装了360全…

【汇编语言】乘法(MUL/IMUL)

乘法(MUL/IMUL) 目录乘法(MUL/IMUL)IMUL(signed multiply)有符号数乘法MUL(unsigned multiply)无符号数乘法麻!属实是被这个有符号乘法给整麻了,教材就一行例子直接不解释了,关于标志位溢出的一…

eclipse快捷键

Java开发工具(Eclipse的视窗和视图概述) A:视窗 每一个基本的窗体被称为视窗 PackageExplorer 显示项目结构,包,类,及资源Outline 显示类的结构,方便查找,识别,修改Console 程序运行的结果在该窗口显示Hie…

【汇编语言】除法(DIV/IDIV)

除法(DIV/IDIV) 目录除法(DIV/IDIV)DIV(unsigned divide)无符号数除法IDIV(signed divide)有符号数除法DIV(unsigned divide)无符号数除法 格式:DIV SRC 操作: SRCSRCSRC为字节时,(AL)←(AX)/…

远控免杀专题(17)-Python-Rootkit免杀

免杀能力一览表 几点说明: 1、上表中标识 √ 说明相应杀毒软件未检测出病毒,也就是代表了Bypass。 2、为了更好的对比效果,大部分测试payload均使用msf的windows/meterperter/reverse_tcp模块生成。 3、由于本机测试时只是安装了360全家桶…

斜视角的讨论(转)

http://school.ogdev.net/listshow.asp?page4&typeid0&categoryid5&id0&ListType2 目 录 1.1 地图和地表 1.2 斜视角游戏中的视角 1.3 Tile图片的拼接 1.4 不同地表间的过渡 1.5 地图数据结构的定义 --------------------------------------------------…

计算机网络(湖科大教书匠)

计算机网络(湖科大教书匠) 本文档为教学视频【计算机网络微课堂(有字幕无背景音乐版)_哔哩哔哩_bilibili】的摘录 目录计算机网络(湖科大教书匠)一、绪论1.2 因特网概述1.2.1 网络、互连网(互联…

远控免杀专题(18)-ASWCrypter免杀

免杀能力一览表 几点说明: 1、上表中标识 √ 说明相应杀毒软件未检测出病毒,也就是代表了Bypass。 2、为了更好的对比效果,大部分测试payload均使用msf的windows/meterperter/reverse_tcp模块生成。 3、由于本机测试时只是安装了360全家桶…

Direct3D中的绘制(3)

立方体——只比三角形稍微复杂一点,这个程序渲染一个线框立方体。 这个简单的绘制和渲染立方体的程序的运行结果如下图所示: 源程序: /************************************************************************************** Renders a …

远控免杀专题(19)-nps_payload免杀

免杀能力一览表 几点说明: 1、上表中标识 √ 说明相应杀毒软件未检测出病毒,也就是代表了Bypass。 2、为了更好的对比效果,大部分测试payload均使用msf的windows/meterperter/reverse_tcp模块生成。 3、由于本机测试时只是安装了360全家桶…

操作系统中的多级队列调度

多级队列调度 (Multilevel queue scheduling) Every algorithm supports a different class of process but in a generalized system, some process wants to be scheduled using a priority algorithm. While some process wants to remain in the system (interactive proce…

借助格式化输出过canary保护

0x01 canary保护机制 栈溢出保护是一种缓冲区溢出攻击缓解手段,当函数存在缓冲区溢出攻击漏洞时,攻击者可以覆盖栈上的返回地址来让shellcode能够得到执行。当启用栈保护后,函数开始执行的时候会先往栈里插入cookie信息,当函数真…

各抓包软件的之间差异_系统软件和应用程序软件之间的差异

各抓包软件的之间差异什么是软件? (What is Software?) Software is referred to as a set of programs that are designed to perform a well-defined function. A program is a particular sequence of instructions written to solve a particular problem. 软件…

ret2shellcdoe

ret2shellcode的关键是找到一个缓冲区&#xff0c;这个缓冲区是可读写写可执行的&#xff0c;我们要想办法把我们的shellcdoe放到这个缓冲区&#xff0c;然后跳转到我们的shellcode处执行。 例子&#xff1a; #include <stdio.h> #include <string.h> char str1[…

远控免杀专题(20)-GreatSCT免杀

转载&#xff1a;https://mp.weixin.qq.com/s/s9DFRIgpvpE-_MneO0B_FQ 免杀能力一览表 几点说明&#xff1a; 1、上表中标识 √ 说明相应杀毒软件未检测出病毒&#xff0c;也就是代表了Bypass。 2、为了更好的对比效果&#xff0c;大部分测试payload均使用msf的windows/mete…

java上传类

publicString doFormFile(FormFile file, String dir) { try { File f new File(dir); if (!f.exists()) { f.mkdir();//如果路径不存在&#xff0c;创建 } InputStream in file.getInputStream(); …

远控免杀专题(21)-HERCULES免杀

转载&#xff1a;https://mp.weixin.qq.com/s/Rkr9lixzL4tiL89r10ndig 免杀能力一览表 几点说明&#xff1a; 1、上表中标识 √ 说明相应杀毒软件未检测出病毒&#xff0c;也就是代表了Bypass。 2、为了更好的对比效果&#xff0c;大部分测试payload均使用msf的windows/mete…

PHP Cookbook读书笔记 – 第16章互联网服务

发送电子邮件 书中主要是以PEAR中的邮件发送类&#xff08;Mail&#xff09;来讲解的&#xff08;关于如何在WIN系统下安装PEAR可以参考WIN下成功安装PEAR&#xff09;。PEAR的MAIL类可以通过3种方式来发送电子邮件&#xff1a; 通过PHP内部的mail函数来发送 通过sendmail程序来…

Python | 使用matplotlib.pyplot创建条形图

Problem statement: Using matplotlib.pyplot library in python draw a bar graph with two values for comparison, using different colors. 问题陈述&#xff1a;在python中使用matplotlib.pyplot库使用不同的颜色绘制带有两个值的条形图以进行比较。 Program: 程序&#…

输出以下的杨辉三角形(要求输入个数字,表示需要输出几行)

#include<stdio.h> int main() {int i,j,k,n,x,a[100][100];a[0][1]1;scanf("%d",&x);for(i1;i<x;i){for(j1;j<i;j){a[i][j]a[i-1][j-1]a[i-1][j];printf("%5d ",a[i][j]);//%5d 表示右对齐隔5个空格&#xff1b;}//同理&#xff0c;%-5d…