`
pterodactyl
  • 浏览: 771392 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

表查询引出问题的解决方法,更多内容请读者参看下文

阅读更多

根据笔者的个人经验 详细介绍了多表查询引出问题的解决 方法,更多内容请读者参看下文:

最近一段时间做公司内部的一个业务 员业绩管理 站点,其中在做报表查询的时候遇到了一个有意思的问题,着实为难了我一下。因为一些不方便的原因,同时也为了便于描述,下面我把这个报表查询简化一下,但是本质上是一样的。

首先是说说表结构吧,一共两张表,暂命名为表T1和T2吧,T1有A,B,C,D四个字段,T2有A,B,C,E四个字段。T2表的A,B两列的联合的值是T1表A,B两列联合的值的子集

我想要的结果是返回一个查询暂命名为T吧,T的结构是 A B C D E,但是T中要包括T1和T2两个表中的所有C的值。看到这里有些博友可能马上就想到了这很简单嘛,一个表连接或右连接就搞定了(的确我一开始也是这样认 为的),但是请注意,我要的结果是要所有C都出现在查询结果中。

为了便于说明问题我们先对两个表添加一些测试数据

T1: A B C D

a1 b1 c1 d1

a2 b2 c2 d2

a3 b3 c3 d3

a4 b4 c4 d4


T2: A B C E

a1 b1 c1 e1

a2 b2 c2 e2

a3 b3 c5 e3

a4 b4 c6 e4

针对于上面两个表的实际数据,也就是结果要像下面这样,也就是要A,B,C三列是联合唯一的

T: A B C D E

a1 b1 c1 d1 e1

a2 b2 c2 d2 e2

a3 b3 c3 d3 null

a4 b4 c4 d4 null

a3 b3 c5 null e3

a4 b4 c6 null e4

乍看之下,两个表的数据合并到一个结果中来,好像还是典型的表连接查询嘛,可是针对我们想要的这个结果来说该用什么想的连接方式呢,inner join?条件呢 T1.A = T2.A and T1.B = T2.B这两个我想应该没有问题的,那C呢,T1.C = T2.C ?好像不对,T1.C is null or T2.C is null ? 更不对了,这样结果行数只会是小于等于T1和T2中的C的不唯一的个数。再来看看left join吧。我们知道,一般情况下,left join的结果的行数只会是等于参加连接的左边表的行数,现在结果的行数是6行,明显不等于T1表的4行。看来左连接的方式也是不行的。那行右连接呢?右 连接从本质上来说和左连接的方式是一样,都是其对应的左连接对称的方式,就像a+b=b+a一样,个人感觉主要是为了某些时候写SQL 的 方便,比如说连续的做连接查询。一般来说左连接能做到的事情,右连接都可以做到,左连接做不到的事情,右连接也同样做不到(扯远了,呵呵)。还有一种方式 cross join,也叫笛卡尔积,交叉连接,不带任何条件的连接,结果行数永远等于T1的行数乘以T2的行数,看看本例,T1有4行,T2有4行,结果确只有6 行,这就更不对了。难道就没有一种办法 可以解决我的问题了吗? 想想以前没有SQLServer 2005 的行时候,连行列互换这样的问题都能够解决,难道现在还搞不定一个小小的连接查询?这两张表的结构相差不多,大不了我把所有的数据都整到一个表里去再来处 理,一个表总比两个表处理起来好吧。咦,慢着,放到一个表里去处理?这到是个办法,没想到我从一句随口说的气话里面忽然看到了一丝希望。可是怎么放呢,最 简单的方法就是union,可是列字段不一样呀。没关系,不存在的列咱给它补上,补成什么就看个人看喜好了,我这里就用null代替了。


说干就干,我马上就写下了第一步中的SQL:

select A,B,C,D,null as E from T1

union

select A,B,C,null as D,E from T2

结果是什么呢:

T: A B C D E

a1 b1 c1 d1 null

a2 b2 c2 d2 null

a3 b3 c3 d3 null

a4 b4 c4 d4 null

a1 b1 c1 null e1

a2 b2 c2 null e2

a3 b3 c5 null e3

a4 b4 c6 null e4

这样总算是把两个表的数据合到一个表了,可是结果是4+4=8行,不是我要的结果6行,怎么办呢。这时我又想到了,我要的结果里A,B,C是联合唯一的, 现在的结果是A,B,C三列不唯一,怎么办呢,直觉告诉我该group by上场了。把不唯一的分组变成唯的分组(以前还从来没有想过group by还有这等用处,呵呵),分组的列好说,就是A,B,C,可是未分组的列需要一个聚合函数呀,我们这里哪用得上聚合呢?看看不唯一的分组内D和E只有有 值和无值两种状态。我又想到了以前分组查询的时候经常用到的min(datetime),max(datetime)这样的用法,取一个分组里的最大,最 小时间,避免了把时间带到group by中去。这里不也是一样的嘛。有值和无值比较当然是有值的大了。

于是对SQL稍加修改变成了下面这样:

select A,B,C,max(D) as D, max(E) as E from

(

select A,B,C,D,null as E from T1

union

select A,B,C,null as D,E from T2

) as T

这样的结果就是我想要的,o了!看似连接的问题不用连接搞定了。

完成后回过头来想想这个真的就不能用连接来做了吗?怎么说也是脱离不了“从两个表里选出不同的列查询”的模式呀。直觉告诉我,如果可行的话只能是用到 left join或right join,可是这两种方式无论是哪一种直接作用于两张表上都会丢失一部分数据。既然两个表直接连接搞不定,能不能临时生成第三张表,再和这两张表作两次连 接,不让原来不该丢失的数据丢掉呢?如果可行的话该怎么构造这个临时表呢?带着这么多的疑问我又仔细考虑了一下,所有的问题最关键的地方是查询结果里面C 的所有值必须全部出现,嗯就是它了。构造一个只有C一列的表把所有的C的值都装进去,这下再连接的话,C的值就不会丢了。SQL如下

select T1.A,T1.B,T.C,T1.D,T2.E from

(

select C from T1

union

select C from T2

) as T

left join T1 on T.C = T1.C

left join T2 on T.C = T2.C

查询的结果跟上面的一样。

旧的问题解决了,新的问题又来了,既然出现了两个答案,两个答案各自的本质是什么呢?谁才是最佳选择呢?对于第一个疑问,我的想法是:group by的方式的本质是把两个表的数据拿出来,按结果的列的唯一性分组,每组对应于结果集里的一行,每个组里只取一行,每列尽量选择不为空的值填充。后者实质 上是先把结果集的行数定下来,也就是选出一个有效的列(本例是C),再用连接的方式取出相应列中的值。顺便说一句,虽然两种方式都用到了union,但是 还是有些细微的差别的,前一种还可以用带all的方式,后一种绝对不能带all,想想也能明白,第一种里面就算是带了all,在后面的group by的时候也会被合并掉的,不会影响最后的结果。至于两者的性能嘛,在数据量少的时候完全可以不考虑的,如果非要问个究竟的话,我也只能说去看看查询计划 生成的图表了。前一种方式做了两次表扫描(T1,T2各一次),一次排序,一次聚合;后一种做了四次表扫描(两次查询,两次连接),一次排序,两次嵌套循 环。谁好谁坏各位自己分析吧。

本以为这件事到些就结束了,可是接下来的一天我又发现了以前一直没有注意到的一点----在MSDN里看到了“全连接”这个概念。以前在刚学连接的时候见 到过,记忆里有这么个印象,只因为平时遇到的问题基本上都能解决,所以对于这个不常用的东东具体含意是什么,什么时候使用,也就不清楚了,时间一长也忘得 差不多了。现在想想全连接的作用就是把参加连接的左表和右表里各自没有的部分也都取到结果集中,放到我现在的这个问题上来看不是正合适的嘛。正所谓“会者 不难,难者不会”,一旦明白了原理 ,相应的SQL也就不难写出来了。

select

case

when T1.A is null then T2.A

else T1.A

end as A,

case

when T1.B is null then T2.B

else T1.B

end as B,

case

when T1.C is null then T2.C

else T1.C

end as C,

T1.D, T2.E

from T1

full join T2 on T1.A = T2.A and T1.B = T2.B and T1.C = T2.C



没有用到union,没有用到临时表,一个连接搞定,代码看着也比较正统,比较优雅。至于这种方式的本质嘛,不用多说了,都在全联接的定义里了。性能方 面,看看查询计划的图表,我实在是没有搞懂怎么一个全联接会进行四次表扫描,一次嵌套循环。难道按照最接近于“查询结果的要求”的定义写出来的SQL性能 还不如第一种用“旁门左道”搞出来的SQL?是我的认知有问题还是本来就是这样的?暂时只能希望有这方面的高手能解答一下了。看来我对于全连接的认识还是 不够呀,以后一定得多多注意,抽个时间好好补上一课。

分享到:
评论

相关推荐

    EAS模板引入引出

    ### EAS模板引入引出知识点详解 #### 一、EAS系统简介 EAS(Enterprise Application Suite)系统是一种广泛应用于企业内部管理的信息技术平台。它能够集成企业的各种业务流程,如财务管理、人力资源管理、供应链...

    K3_BOM单引出引入方法.doc

    K3_BOM单引出引入方法,主要涉及的是如何在K3系统中对BOM数据进行导出(引出)和导入(引入),这对于数据维护和系统升级有着重要的意义。 ### K3_BOM单引出(导出)方法 #### 1. 准备工作 在进行BOM数据的引出...

    url传递的参数值中包含&时,url自动截断问题的解决方法

    一、问题的引出 在做一个公告浏览功能时,只要通过url传递的某参数值中包含 & 或 ,就会出现问题–该变量的值无法显示。 问题定位结果: 遇到&时,该参数的值会自动截断,导致参数值传递有误。 二、问题的解决 java...

    爱普生R230废墨引出方法

    "废墨引出方法"是解决这一问题的关键步骤,下面将详细解释废墨的产生、废墨引出的重要性以及具体的操作步骤。 废墨是指打印机在清洁喷头和初始化过程中产生的墨水,这些墨水并未用于实际打印,而是被设计成排入...

    K3标准凭证引入、引出

    ### K3标准凭证引入、引出相关知识点 #### 一、概述 金蝶K3是一款广泛应用于企业财务管理的软件,其强大...了解上述常见问题及其解决方案,有助于用户更加熟练地掌握这一功能,从而更好地服务于企业的财务管理需求。

    用Maple和MATLAB解决科学计算问题(第三版)

    描述部分提到“用Maple和MATLAB解决科学计算问题,通过实例讲解深入学习MATLAB解决实际问题的方法”,这进一步明确了本书的主要内容。除了理论知识外,书中还会包含许多实践案例,以帮助读者更好地理解和掌握如何...

    引出端及整体安装件强

    根据提供的信息,我们可以了解到这份文档主要涉及的是GBT 2423.60-2008《电工电子产品环境试验 第2部分:试验方法 试验U:引出端及整体安装件强度》的相关内容。虽然部分内容仅显示了标准分享网站的信息,并没有提供...

    matlabsimulink中代数环问题的讲解及解决方法1-解决代数环方法.doc

    Simulink在处理代数环问题时,通常会尝试使用牛顿法等数值方法来寻找解决方案。然而,牛顿法并不总是能保证收敛到一个解,特别是在复杂的代数环结构中。因此,最佳的做法是在模型搭建阶段就预防代数环的出现,而不是...

    铺垫、伏笔、引出下文的区别.doc

    铺垫,又称铺叙衬垫,是文学创作中一种常见的手法,通过描述次要情节或细节来衬托、预示即将出现的主要人物、事物或事件,为主要内容创造背景和氛围。铺垫通常起到蓄势、增强情节力度的作用,使得故事发展更为连贯...

    电子政务-炉水泵电机引出线制作方法.zip

    了解这些基本步骤后,电子政务领域的技术人员能够更好地理解和执行炉水泵电机引出线的制作,从而确保设备的可靠运行。同时,定期的检查和维护也是保证电机长期稳定工作的必要措施,包括对引出线的老化、磨损情况进行...

    新人教二年级数学上册解决问题连续两问PPT学习教案.pptx

    本篇教案针对的是新人教二年级数学上册的内容,特别设计了关于解决这类问题的教学流程。 教案开始部分,教师先引导学生复习基础的加法和减法知识。这是因为在解决连续两问的问题时,加减法是必要的基本技能。为了使...

    水滴石穿C语言之编译器引出的问题.doc

    《水滴石穿C语言之编译器引出的问题》 C语言的编译过程具有其独特的特性,这些特性在编程实践中可能导致一些不常见的问题。本文主要探讨了两个关键方面:C文件的分别编译以及函数参数和返回值的处理方式。 首先,...

    三年级数学下册铺地砖解决问题PPT课件.pptx

    本篇文章将围绕三年级数学下册铺地砖解决问题PPT课件,深入分析学习中所涉及的关键知识点,并结合具体实例对面积计算、数量计算以及解决问题的方法和步骤进行详细阐释。 一、铺地砖的面积计算 在铺地砖的过程中,...

    一道面试题引出的系列数据库性能,数据安全问题及解决方案.docx

    - 表名和字段定义: 确保表名和字段的含义清晰,如`girls`表可能需要更明确的名称,`age`字段更适合存储`出生日期`而非当前年龄,`boyfriend`字段的含义和存储格式需要明确,以避免误解和查询错误。 - 数据类型选择...

    解决无棱角零件切割引入引出缺陷的工艺研究

    在现代制造领域,尤其是在重型机械行业中,无棱角零件的高精度切割对于保障产品质量和生产效率具有重要意义。...它将为切割无棱角零件的行业提供可靠的技术支持,有助于推动行业向更高效、更精准、更节能的方向发展。

    《一年级下册智慧广场——用表格列举法解决问题》教学设计.pdf

    教师的指导和学生的自主探索是相互配合的,通过这种方式,学生可以更好地理解和掌握用表格列举法解决问题的方法。 本教学设计的优点是可以帮助学生巩固画图法,学习用表格列举法解决问题,并体会数字列举法解决问题...

    实现“解决问题”的深度学习.pdf

    数据分析作为一种工具和方法,可以帮助学生在面对复杂问题时,通过收集和分析数据,找出问题的规律和解决问题的关键点。在这个过程中,数据研究的技能成为了学生解决问题不可或缺的一部分。而参考文献和专业指导则是...

    用除法解决问题说课稿.doc

    - "用除法解决问题"这节课是在学生掌握7-9乘法口诀之后进行的,旨在深化学生对除法的理解,提供更多的除法练习,并建立数学与实际生活的联系,培养应用数学的意识和解决问题的能力。 - 教材通过逐步深入的方式安排...

    新人教二年级数学上册表内乘法一解决问题PPT课件.pptx

    新教版二年级数学上册的表内乘法单元教学是小学生数学学习的一个重要阶段,它不仅涉及到基础算术知识的学习,更是培养学生逻辑思维和解决问题能力的起点。本PPT课件通过精心设计的教学环节,旨在让学生在轻松愉快的...

Global site tag (gtag.js) - Google Analytics