一、Mysql中Left/Right join on后面and和where条件查询的差异

1、建两张测试表,一张商户定义表、一张商户操作状态明细表

1)商户定义表

CREATE TABLE hope.merchant (
  MERCHANT_id varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

2)商户操作明细表

CREATE TABLE trade_info (
  MERCHANT_NO varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  TRADE_STATUS varchar(30) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  CREATE_TIME datetime DEFAULT current_timestamp()
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

2.测试Left/Right join on后面and和where条件查询的差异

普通left join演示

select a.MERCHANT_id,b.MERCHANT_NO,b.TRADE_STATUS from hope.merchant a left join hope.trade_info b
  on a.MERCHANT_id=b.MERCHANT_NO;

select count(1) from hope.merchant a left join hope.trade_info b
  on a.MERCHANT_id=b.MERCHANT_NO;--》82行数据

结果:可以看到,部分商户在某段时间内事没有任何操作的,所以,左表hope.merchant的商户,没有对应的操作,会用Null补足。

1)Left/Right join on后面带and

select a.MERCHANT_id,b.MERCHANT_NO,b.TRADE_STATUS,b.CREATE_TIME from hope.merchant a left join hope.trade_info b
  on a.MERCHANT_id=b.MERCHANT_NO and b.CREATE_TIME>'2018-12-19 19:00:00';

select count(1) from hope.merchant a left join hope.trade_info b
  on a.MERCHANT_id=b.MERCHANT_NO and b.CREATE_TIME>'2018-12-19 19:00:00';  ----》69行数据

2)Left/Right join on后面带where

select a.MERCHANT_id,b.MERCHANT_NO,b.TRADE_STATUS,b.CREATE_TIME from hope.merchant a left join hope.trade_info b
  on a.MERCHANT_id=b.MERCHANT_NO where b.CREATE_TIME>'2018-12-19 19:00:00';

select count(1) from hope.merchant a left join hope.trade_info b
  on a.MERCHANT_id=b.MERCHANT_NO where b.CREATE_TIME>'2018-12-19 19:00:00'; --》43行数据

3)对比结果

语句一是on and ,一句是 on where,下的条件类似,但是结果却是完全不同。带where的过滤掉了左连接中左表没有任何操作记录的商户号,

但是使用and的却没有,并得到了我想要的结果。Why???

二、Mysql 运算符是有优先级

1.总结SQL优先级

where是对已经搜索出的结果的过滤条件

on是两者join形成新表时用到的匹配条件

大家可能看出一些规律,在on的情况下and(或者or)与on同时对前面的集合起作用,而存在where的时候,先对集合进行on条件的抽取,在根据where的条件进行抽取.这是个值得注意的地方.
说下原因:
(1)ON后面的筛选条件主要是针对的是关联表【而对于主表筛选条件不适用】;
(2)对于主表的筛选条件应放在where后面,不应该放在ON后面;
(3)对于关联表我们要区分对待。如果是要条件查询后才连接应该把查询件放置于ON后;如果是想再连接完毕后才筛选就应把条件放置于where后面;
(4)对于关联表我们其实可以先做子查询再做join。

2.总结sql类型,尽量不写子查询

1)对于关联表我们其实可以先做子查询再做join,此SQL运行3.5秒

select MERCHANT_ID,case when rait is null then 0 else  rait end
from (
select MERCHANT_ID,
TRUNCATE(count(case when c.trade_status ='SUCCESS' then 1 else null end)*100/count(case when c.trade_status !='FAILED' then 1 else null end),2) rait 
from ifpay_ccpay.merchant a left join (
select * from ifpay_ccpay.trade_info b where b.CREATE_TIME > date_add(now(), interval - 30 minute)
and b.method='H5') c on a.MERCHANT_ID=c.MERCHANT_NO group by a.MERCHANT_ID) d;

2)不做子查询运行14ms

select MERCHANT_ID,case when rait is null then 0 else  rait end
from (
select MERCHANT_ID,
TRUNCATE(count(case when b.trade_status ='SUCCESS' then 1 else null end)*100/count(case when b.trade_status !='FAILED' then 1 else null end),2) rait 
from ifpay_ccpay.merchant a left join ifpay_ccpay.trade_info b on a.MERCHANT_ID=b.MERCHANT_NO
and b.CREATE_TIME > date_add(now(), interval - 30 minute)
and b.method='H5'  group by a.MERCHANT_ID) D;

Mysql 中Left/Right join on后面and和where条件查询的差异-Mysql SQL运算符是有优先级的更多相关文章

  1. MySQL中使用INNER JOIN来实现Intersect并集操作

    MySQL中使用INNER JOIN来实现Intersect并集操作 一.业务背景 我们有张表设计例如以下: CREATE TABLE `user_defined_value` ( `RESOURCE ...

  2. 关于MySQL中的left join、on、where的一点深入

    原文地址:http://www.oschina.net/question/89964_65912?sort=default&p=3#answers 即使你认为自己已对 MySQL 的 LEFT ...

  3. 使用Mysql中的concat函数或正则匹配来快速批量生成用于执行的sql语句

    背景介绍 今天需要给一张表里面补数据,需要按照行的维度进行update,如果是个别数据那么直接写update语句就可以了,但是场景要求的是将整表的数据进行update,要实现这个需求就不能只靠蛮力了, ...

  4. Mysql高手系列 - 第7篇:玩转select条件查询,避免踩坑

    这是Mysql系列第7篇. 环境:mysql5.7.25,cmd命令中进行演示. 电商中:我们想查看某个用户所有的订单,或者想查看某个用户在某个时间段内所有的订单,此时我们需要对订单表数据进行筛选,按 ...

  5. oracle 在xml中批量插入,批量修改及多组条件查询

    最近公司用ibatis开发项目,本来可以用存储过程处理批量插入,批量修改及多组条件查询:但由于使用模块相对较小,暂时就在xml中配置,以前没有在xml做过类似处理,有必要记录一下:好了,代码如下: & ...

  6. MySQL中日期与字符串相互转换,并进行日期比较查询

    技术交流群:233513714 1.日期无需转换查询(日期在数据库中的类型为字符串) select * from day where dateTime > '2016-03-15' 2.使用da ...

  7. 多条件查询(php+mysql) 租房子例子

    <body> <?php //多条件 $tiaojian2= " 2=2 "; $attr2 = ""; //判断区域 if(!empty($ ...

  8. MySQL中链接查询inner join与left join使用

    连接查询其实就是对两个表记录做笛卡尔乘积.如果不指定连接条件的话,则会对每行都做笛卡尔乘积,这样最后返回的结果树就会是两个表记录数的乘积:如果指定则,则仅对符合列条件的行进行笛卡尔乘积,并返回结果.在 ...

  9. mysql中的几种join 及 full join问题

    [注意]:Oracle数据库支持full join,mysql是不支持full join的,但仍然可以同过左外连接+ union+右外连接实现 初始化SQL语句:   /*join 建表语句*/   ...

随机推荐

  1. Delphi XE5 for Android (一)

    Delphi XE5 出来了,支持Android的开发,试用了一下,有几个问题: 1.只支持ARM7的设备,不支持Inter设备.手上刚好有一个华硕K004,很遗憾用不上,只能用手机试了. 2.要支持 ...

  2. linux磁盘分区详解【转】

    本文装载自:http://blog.csdn.net/aaronychen/article/details/2270048#comments 在学习 Linux 的过程中,安装 Linux 是每一个初 ...

  3. LightOJ 1229 Treblecross(SG函数打表 + 遍历)题解

    题意:给你一串含“.”和“X”的字串,每次一个玩家可以把‘."变成“X”,谁先弄到三个XXX就赢.假如先手必赢,输出所有能必赢的第一步,否则输出0. 思路:显然如果一个X周围两格有X那么肯定 ...

  4. 9.1C#中类的定义

    9.1 C#中类的定义 C#使用class关键字来定义类   [默认internal] class MyClass { //Class Members } 在默认情况下,类声明为内部的,即只有当前项目 ...

  5. Wannafly 挑战赛22 D 整数序列 线段树 区间更新,区间查询

    题目链接:https://www.nowcoder.com/acm/contest/160/D 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 262144K,其他语言524288K ...

  6. POJ 1953 World Cup Noise(递推)

    https://vjudge.net/problem/POJ-1953 题意:输入一个n,这n位数只由0和1组成,并且不能两个1相邻.计算共有多少种排列方法. 思路:递推题. 首先a[1]=2,a[2 ...

  7. UVa 12186 工人的请愿书(树形DP)

    https://vjudge.net/problem/UVA-12186 题意: 一个老板和n个员工组成树状结构,每个员工都有自己的唯一上司,老板的编号为0,员工1~n,工人们打算签署一个志愿书给老板 ...

  8. 【NOI2014】动物园

    题目链接:http://uoj.ac/problem/5 求:$${\prod _{i=1}^{L}num[i]\%(1e9+7)}$$,${num\left [ i \right ]}$表示:由字符 ...

  9. python 数据交换

    例1 def change(data): data[],data[]=data[],data[] print('函数内交换位置后:') ): print('data[%d]=%3d' %(i,data ...

  10. Python day7_set集合的常用方法以及常用格式化的总结

    1.集合的定义:集合是无序的,没有重合元素的集合 集合外使用{}符号,各元素用,连接 2.集合的常用方法 1.add增加元素 2.clear清除元素 3.copy浅拷贝 4.difference差集( ...