菜鸟日记(2013-5-8)-关于两句SQL语句得到的启示

这个是第一个语句:
SELECT  * from T_CarInfo
where T_CarInfo.CarID not in (
            SELECT 
    T_RepairBill.CarID
            FROM 
T_RepairBillRepairType 
LEFT JOIN T_RepairBill 
ON T_RepairBillRepairType.RepairBillCode = T_RepairBill.RepairBillCode AND T_RepairBillRepairType.PointCode = T_RepairBill.PointCode
LEFT JOIN T_ComParameter
ON T_RepairBillRepairType.RepairType=T_ComParameter.ParameterFlag and T_RepairBillRepairType.PointCode=T_ComParameter.PointCode
where  T_ComParameter.MaintenanceFlag=1
AND
(T_RepairBillRepairType.PointCode IN (SELECT PointCode FROM DBO.F_GetRelationPointCollection('0', 1, 1, -1 * ISNULL(0, 0), 1)))

 and (T_CarInfo.PointCode IN (SELECT PointCode FROM DBO.F_GetRelationPointCollection('0', 1, 1, -1 * ISNULL(0, 0), 1)))

 这个是第二个语句:
 SELECT  * from T_CarInfo
    where NOT exists(
        SELECT  
      1
            FROM 
T_RepairBillRepairType
LEFT JOIN T_RepairBill 
ON T_RepairBillRepairType.RepairBillCode = T_RepairBill.RepairBillCode AND T_RepairBillRepairType.PointCode = T_RepairBill.PointCode
LEFT JOIN T_ComParameter
ON T_RepairBillRepairType.RepairType=T_ComParameter.ParameterFlag and T_RepairBillRepairType.PointCode=T_ComParameter.PointCode
where  T_ComParameter.MaintenanceFlag=1 
AND T_RepairBill.CarID=T_CarInfo.CarID
AND
(T_RepairBillRepairType.PointCode IN (SELECT PointCode FROM DBO.F_GetRelationPointCollection('0', 1, 1, -1 * ISNULL(0, 0), 1)))
        )
        and (T_CarInfo.PointCode IN (SELECT PointCode FROM DBO.F_GetRelationPointCollection('0', 1, 1, -1 * ISNULL(0, 0), 1)))
查询出来的结果无疑第二句是正确的,第一句是空的。
我不明白的是第一个语句与第二个语句所要表达的意义是一样的,都是排除T_ComParameter.MaintenanceFlag=1 
这种情况下的数据信息。为什么第一个语句查询的是空的呢?

我把子查询拿出来执行了一下:

SELECT row_number() over(order by T_RepairBill.CarID), T_RepairBill.CarID
            FROM 
T_RepairBillRepairType 
LEFT JOIN T_RepairBill 
ON T_RepairBillRepairType.RepairBillCode = T_RepairBill.RepairBillCode AND T_RepairBillRepairType.PointCode = T_RepairBill.PointCode
LEFT JOIN T_ComParameter
ON T_RepairBillRepairType.RepairType=T_ComParameter.ParameterFlag and T_RepairBillRepairType.PointCode=T_ComParameter.PointCode
where  T_ComParameter.MaintenanceFlag=1 
--and T_RepairBill.RepairBillCode is not null

像这样得到数据确实有空的存在。毕竟T_RepairBill 不是主表,存在空的CarID也是很正常的。

那么有空的CarID是否有影响呢,答案是肯定的。

原因是这样的:

IN或NOT IN就是几个OR的联合
where a NOT IN(1,2,3)就是
where a=1 or a=2 or a=3
而对NULL值的判断是用IS NULL,IS NOT NULL来的
写A=NULL或者A!=NULL肯定是没结果的
对比着两种的Sql写法,就不由自主的对比EXists与in 的优略性。这里有一段文字关于两种写法的对比:

in和exists执行时,in是先执行子查询中的查询,然后再执行主查询。而exists查询它是先执行主查询,即外层表的查询,然后再执行子查询。

exists 和 in 在执行时效率单从执行时间来说差不多,exists要稍微优于in。在使用时一般应该是用exists而不用in

如果子查询得出的结果集记录较少,主查询中的表较大且又有索引时应该用in,反之如果外层的主查询记录较少,子查询中的表大,又有索引时使用exists。IN时不对NULL进行处理。

        not exists 和 not in 比较时,not exists 的效率比较高。

        为了说明测试结果,我把emp1表中的数据到了315392条。emp2中删除只有2条件数据。测试的依据是执行的时间来说明的。

        emp1中的数据记录情况。

                SQL> select count(*) from emp1;

  COUNT(*)

----------

315392

emp2中的数据记录情况:

SQL> select count(*) from emp2;

 

  COUNT(*)

----------

   2

1、  执行exists查询,要求在emp1中查询出所有存在于emp2的数据总数

 SQL> select count(*) from emp1 where exists ( select null from emp2 where emp1.ename = emp2.ename);

  COUNT(*)

----------

     45056

执行次数十次,最大的一次为0.125S

2、    使用not exists查询出所在不在emp2中的数据总数

SQL> select count(*) from emp1 where not exists ( select null from emp2 where emp1.ename = emp2.ename);

     COUNT(*)

----------

270336

执行次数十次,最大的一次为0.141S

3、执行in 查询,要求在emp1中查询出所有存在于emp2的数据总数

SQL> select count(*) from emp1 where ename in ( select ename from emp2);

  COUNT(*)

----------

     45056

执行十次,最大的一次为0.141S

4、使用not in查询出所在不在emp2中的数据总数

SQL> select count(*) from emp1 where ename not in ( select ename from emp2 );

  COUNT(*)

----------

270336

执行十次,最长一次为0.328S

5、使用in查询,调用外层与子查询的位置,要求查询出存在于emp2中,且存在于emp1中的数据记录数

SQL> select count(*) from emp2 where ename in (select ename from emp1 );

  COUNT(*)

----------

         2

执行次数十次,最长的一次为0.047S

6、使用exists查询,调用外层与子查询的位置,要求查询出存在于emp2中,且存在于emp1中的数据记录数

SQL> select count(*) from emp2 where ename in (select ename from emp1 );

  COUNT(*)

----------

         2

执行次数十次,最长的一次为0.047S

综上所述:在使用in 和 exists时,个人觉得,效率差不多。而在not in 和 not exists比较时,not exists的效率要比not in的效率要高。

当使用in时,子查询where条件不受外层的影响,自动优化会转成exist语句,它的效率和exist一样。(没有验证)

如select * from t1 where f1 in (select f1 from t2 where t2.fx='x') 这时,认为in 和 exists效率一样。

IN适合于外表大而内表小的情况;EXISTS适合于外表小而内表大的情况。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值