SQL中过滤条件放在on和where中的区别

今天接到蚂蚁金服的电面,问了sql中过滤条件放在on和where中的区别,当时满脑子是inner join,觉得没区别啊。后来才想起来,连接查询除了inner join还有right join,left join。汗呐,当时还是太紧张了。这里做一下记录吧。

join过程可以这样理解:首先两个表做一个笛卡尔积,on后面的条件是对这个笛卡尔积做一个过滤形成一张临时表,如果没有where就直接返回结果,如果有where就对上一步的临时表再进行过滤。下面看实验:

先准备两张表:


先执行inner join:

select * from person p inner join account a on p.id=a.id and p.id!=4 and a.id!=4;

select * from person p inner join account a on p.id=a.id where p.id!=4 and a.id!=4;

结果没有区别,前者是先求笛卡尔积然后按照on后面的条件进行过滤,后者是先用on后面的条件过滤,再用where的条件过滤。


再看看左连接left join

select * from person p left join account a on p.id=a.id and p.id!=4 and a.id!=4;

这下看出来不对了,id为4的记录还在,这是由left join的特性决定的,使用left join时on后面的条件只对右表有效(可以看到右表的id=4的记录没了)

select * from person p left join account a on p.id=a.id where p.id!=4 and a.id!=4;

where的过滤作用就出来了。。。

右连接的原理是一样的。。


到这里就真相大白了inner join中on和where没区别,右连接和左连接就不一样了。

  • 27
    点赞
  • 62
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
支持 MS SQL 2005 之前的版本 不支持 sql 2008 介绍 Log Explorer主要用于对MSSQLServer的事物分析和数据恢复。你可以浏览日志、导出数据、恢复被修改或者删除的数据(包括执行过update,delete,drop和truncate语句的表格)。一旦由于系统故障或者人为因素导致数据丢失,它能够提供在线快速的数据恢复,最大程度上保证恢复期间的其他事物不间断执行。 他可以支持SQLServer7.0、SQLServer2000和SQLServer2005,提取标准数据库的日志文件或者备份文件的信息。 其提供两个强大的工具:日志分析浏览,对象恢复。具体功能如下: l 日志文件浏览 l 数据库变更审查 l 计划和授权变更审查 l 将日志记录导出到文件或者数据库表 l 实时监控数据库事物 l 计算并统计负荷 l 通过有选择性的取消或者重做事物来恢复数据 l 恢复被截断或者删除表的数据 l 运行SQL脚本 产品 LogExplore包含两部分 l 客户端软件 l 服务器代理 服务器端代理是保存在SQLServer主机的一个只读存储过程,他的作用是接受客户端请求,读取在线事物日志块并通过网络传给客户端软件,由客户端软件来读取这些原始的数据块来完成Log Explore所提供的所有功能。 他依赖来的网络协议包括: l Named Pipe:局域网适用 l Tcp/Ip:广域网适用 数据库相关介绍 事物日志(Transaction Log) SQLServer的每个数据库都包含事物日志,它以文件的形式存储,可以记录数据库的任何变化。发生故障时SQLServer就是通过它来保证数据的完整性。 操作(Operation) 操作是数据库定义的"原子行为",每个操作都在日志文件保存为一条记录。它可以是用户直接输入的SQL语句,比如标准的insert命令,日志文件便会记录一条操作代码来标志这个insert操作。 事物(Transaction) 事物是一系列操作组成的序列。他可以理解为直观的不可分割的一笔业务,可以执行成功或者失败。典型的事物比如由应用程序发出的具有开启-提交功能的一组SQL语句。不同的事物靠事物Id号(transaction ID)来区分,具有相同ID的事物记录的日志也相同。 在线事物日志(Online Transaction Log) 在线事物日志是指当前活动数据库所用的日志。可以通过如下命令来确定其对应文件 Select * from SYSFILES 他的文件后缀名一般是.LDF 离线事物日志(Offline Transaction Log) 离线事物日志是指非活动数据库所用的日志。当其数据库处于关闭(ShutDown)才状态下可以进行复制备份操作。他的结果同在线事物日志完全相同。 备份文件 备份文件是保存食物日志备份的文件,通常管理员通过运行SQL语句或者企业管理器来生成该文件。备份文件的内部结构和事物日志不同,他采用称为MTF的格式来保存数据。一个备份文件可以包含一个日志的多组备份,甚至包括多个数据库的混合备份. 设置为自动收缩 企业管理器--服务器--右键数据库--属性--选项--选择"自动收缩" 强烈要求该项不要选.否则SQLServer将已循环的方式来覆盖先前的日志记录,将会导致LogExplore无法恢复错误. 数据恢复介绍 LogExplore允许你恢复应为误操作或者程序错误而导致的数据丢失或者更改.比如执行update\Delete语句时丢失了where子句,或者错误使用了Dts功能. LogExplore不支持直接修改数据库.他可以生成事物的逆操作脚本. 如果log是delete table where ...的话,生成的文件代码就是insert table .... 你可以通过SQL查询分析器,或者LogExplore的Run SQL Script功能来执行生成脚本. 关于Undo Undo功能可以逆操作一组指定的用户事物。包括insert,delete和update,其局限性如下: l 事物类别:LogExplore只能undo用户事物。用户事物是指在用户表上定义的事物,不支持系统表的更新恢复。同时,他也不支持计划变更的回滚。 l Blob类型:包括text,ntext,image类型。LogExplore只支持这些类型的insert和delete恢复,不支持update语句恢复。 关于redo Redo功能可以再次运行一组指定事物。它可以在以下情况用到: 丢失数据库而且没有任何备份文件。 l 如果原始日志文件没有丢失可以通过Redo来实现恢复。 l
--高级查询在数据库用得是最频繁的,也是应用最广泛的。 Ø 基本常用查询 --select select * from student; --all 查询所有 select all sex from student; --distinct 过滤重复 select distinct sex from student; --count 统计 select count(*) from student; select count(sex) from student; select count(distinct sex) from student; --top 取前N条记录 select top 3 * from student; --alias column name 列重命名 select id as 编号, name '名称', sex 性别 from student; --alias table name 表重命名 select id, name, s.id, s.name from student s; --column 列运算 select (age + id) col from student; select s.name + '-' + c.name from classes c, student s where s.cid = c.id; --where 条件 select * from student where id = 2; select * from student where id > 7; select * from student where id < 3; select * from student where id <> 3; select * from student where id >= 3; select * from student where id <= 5; select * from student where id !> 3; select * from student where id !< 5; --and 并且 select * from student where id > 2 and sex = 1; --or 或者 select * from student where id = 2 or sex = 1; --between ... and ... 相当于并且 select * from student where id between 2 and 5; select * from student where id not between 2 and 5; --like 模糊查询 select * from student where name like '%a%'; select * from student where name like '%[a][o]%'; select * from student where name not like '%a%'; select * from student where name like 'ja%'; select * from student where name not like '%[j,n]%'; select * from student where name like '%[j,n,a]%'; select * from student where name like '%[^ja,as,on]%'; select * from student where name like '%[ja_on]%'; --in 子查询 select * from student where id in (1, 2); --not in 不在其 select * from student where id not in (1, 2); --is null 是空 select * from student where age is null; --is not null 不为空 select * from student where age is not null; --order by 排序 select * from student order by name; select * from student order by name desc; select * from student order by name asc; --group by 分组 按照年龄进行分组统计 select count(age), age from student group by age; 按照性别进行分组统计 select count(*), sex from student group by sex; 按照年龄和性别组合分组统计,并排序 select count(*), sex from student group by sex, age order by age; 按照性别分组,并且是id大于2的记录最后按照性别排序 select count(*), sex from student where id > 2 group by sex order by sex; 查询id大于2的数据,并完成运算后的结果进行分组和排序 select count(*), (sex * id) new from student where id > 2 group by sex * id order by sex * id; --group by all 所有分组 按照年龄分组,是所有的年龄 select count(*), age from student group by all age; --having 分组过滤条件 按照年龄分组,过滤年龄为空的数据,并且统计分组的条数和现实年龄信息 select count(*), age from student group by age having age is not null; 按照年龄和cid组合分组,过滤条件是cid大于1的记录 select count(*), cid, sex from student group by cid, sex having cid > 1; 按照年龄分组,过滤条件是分组后的记录条数大于等于2 select count(*), age from student group by age having count(age) >= 2; 按照cid和性别组合分组,过滤条件是cid大于1,cid的最大值大于2 select count(*), cid, sex from student group by cid, sex having cid > 1 and max(cid) > 2; Ø 嵌套子查询 子查询是一个嵌套在select、insert、update或delete语句或其他子查询的查询。任何允许使用表达式的地方都可以使用子查询。子查询也称为内部查询或内部选择,而包含子查询的语句也成为外部查询或外部选择。 # from (select … table)示例 将一个table的查询结果当做一个新表进行查询 select * from ( select id, name from student where sex = 1 ) t where t.id > 2; 上面括号的语句,就是子查询语句(内部查询)。在外面的是外部查询,其外部查询可以包含以下语句: 1、 包含常规选择列表组件的常规select查询 2、 包含一个或多个表或视图名称的常规from语句 3、 可选的where子句 4、 可选的group by子句 5、 可选的having子句 # 示例 查询班级信息,统计班级学生人生 select *, (select count(*) from student where cid = classes.id) as num from classes order by num; # in, not in子句查询示例 查询班级id大于小于的这些班级的学生信息 select * from student where cid in ( select id from classes where id > 2 and id < 4 ); 查询不是班的学生信息 select * from student where cid not in ( select id from classes where name = '2班' ) in、not in 后面的子句返回的结果必须是一列,这一列的结果将会作为查询条件对应前面的条件。如cid对应子句的id; # exists和not exists子句查询示例 查询存在班级id为的学生信息 select * from student where exists ( select * from classes where id = student.cid and id = 3 ); 查询没有分配班级的学生信息 select * from student where not exists ( select * from classes where id = student.cid ); exists和not exists查询需要内部查询和外部查询进行一个关联的条件,如果没有这个条件将是查询到的所有信息。如:id等于student.id; # some、any、all子句查询示例 查询班级的学生年龄大于班级的学生的年龄的信息 select * from student where cid = 5 and age > all ( select age from student where cid = 3 ); select * from student where cid = 5 and age > any ( select age from student where cid = 3 ); select * from student where cid = 5 and age > some ( select age from student where cid = 3 ); Ø 聚合查询 1、 distinct去掉重复数据 select distinct sex from student; select count(sex), count(distinct sex) from student; 2、 compute和compute by汇总查询 对年龄大于的进行汇总 select age from student where age > 20 order by age compute sum(age) by age; 对年龄大于的按照性别进行分组汇总年龄信息 select id, sex, age from student where age > 20 order by sex, age compute sum(age) by sex; 按照年龄分组汇总 select age from student where age > 20 order by age, id compute sum(age); 按照年龄分组,年龄汇总,id找最大值 select id, age from student where age > 20 order by age compute sum(age), max(id); compute进行汇总前面是查询的结果,后面一条结果集就是汇总的信息。compute子句可以添加多个汇总表达式,可以添加的信息如下: a、 可选by关键字。它是每一列计算指定的行聚合 b、 行聚合函数名称。包括sum、avg、min、max、count等 c、 要对其执行聚合函数的列 compute by适合做先分组后汇总的业务。compute by后面的列一定要是order by出现的列。 3、 cube汇总 cube汇总和compute效果类似,但语法较简洁,而且返回的是一个结果集。 select count(*), sex from student group by sex with cube; select count(*), age, sum(age) from student where age is not null group by age with cube; cube要结合group by语句完成分组汇总 Ø 排序函数 排序在很多地方需要用到,需要对查询结果进行排序并且给出序号。比如: 1、 对某张表进行排序,序号需要递增不重复的 2、 对学生的成绩进行排序,得出名次,名次可以并列,但名次的序号是连续递增的 3、 在某些排序的情况下,需要跳空序号,虽然是并列 基本语法 排序函数 over([分组语句] 排序子句[desc][asc]) 排序子句 order by 列名, 列名 分组子句 partition by 分组列, 分组列 # row_number函数 根据排序子句给出递增连续序号 按照名称排序的顺序递增 select s.id, s.name, cid, c.name, row_number() over(order by c.name) as number from student s, classes c where cid = c.id; # rank函数函数 根据排序子句给出递增的序号,但是存在并列并且跳空 顺序递增 select id, name, rank() over(order by cid) as rank from student; 跳过相同递增 select s.id, s.name, cid, c.name, rank() over(order by c.name) as rank from student s, classes c where cid = c.id; # dense_rank函数 根据排序子句给出递增的序号,但是存在并列不跳空 不跳过,直接递增 select s.id, s.name, cid, c.name, dense_rank() over(order by c.name) as dense from student s, classes c where cid = c.id; # partition by分组子句 可以完成对分组的数据进行增加排序,partition by可以与以上三个函数联合使用。 利用partition by按照班级名称分组,学生id排序 select s.id, s.name, cid, c.name, row_number() over(partition by c.name order by s.id) as rank from student s, classes c where cid = c.id; select s.id, s.name, cid, c.name, rank() over(partition by c.name order by s.id) as rank from student s, classes c where cid = c.id; select s.id, s.name, cid, c.name, dense_rank() over(partition by c.name order by s.id) as rank from student s, classes c where cid = c.id; # ntile平均排序函数 将要排序的数据进行平分,然后按照等分排序。ntile的参数代表分成多少等分。 select s.id, s.name, cid, c.name, ntile(5) over(order by c.name) as ntile from student s, classes c where cid = c.id; Ø 集合运算 操作两组查询结果,进行交集、并集、减集运算 1、 union和union all进行并集运算 --union 并集、不重复 select id, name from student where name like 'ja%' union select id, name from student where id = 4; --并集、重复 select * from student where name like 'ja%' union all select * from student; 2、 intersect进行交集运算 --交集(相同部分) select * from student where name like 'ja%' intersect select * from student; 3、 except进行减集运算 --减集(除相同部分) select * from student where name like 'ja%' except select * from student where name like 'jas%'; Ø 公式表表达式 查询表的时候,有时候间表需要重复使用,这些子查询被重复查询调用,不但效率低,而且可读性低,不利于理解。那么公式表表达式可以解决这个问题。 我们可以将公式表表达式(CET)视为临时结果集,在select、insert、update、delete或是create view语句的执行范围内进行定义。 --表达式 with statNum(id, num) as ( select cid, count(*) from student where id > 0 group by cid ) select id, num from statNum order by id; with statNum(id, num) as ( select cid, count(*) from student where id > 0 group by cid ) select max(id), avg(num) from statNum; Ø 连接查询 1、 简化连接查询 --简化联接查询 select s.id, s.name, c.id, c.name from student s, classes c where s.cid = c.id; 2、 left join左连接 --左连接 select s.id, s.name, c.id, c.name from student s left join classes c on s.cid = c.id; 3、 right join右连接 --右连接 select s.id, s.name, c.id, c.name from student s right join classes c on s.cid = c.id; 4、 inner join内连接 --内连接 select s.id, s.name, c.id, c.name from student s inner join classes c on s.cid = c.id; --inner可以省略 select s.id, s.name, c.id, c.name from student s join classes c on s.cid = c.id; 5、 cross join交叉连接 --交叉联接查询,结果是一个笛卡儿乘积 select s.id, s.name, c.id, c.name from student s cross join classes c --where s.cid = c.id; 6、 自连接(同一张表进行连接查询) --自连接 select distinct s.* from student s, student s1 where s.id <> s1.id and s.sex = s1.sex; Ø 函数 1、 聚合函数 max最大值、min最小值、count统计、avg平均值、sum求和、var求方差 select max(age) max_age, min(age) min_age, count(age) count_age, avg(age) avg_age, sum(age) sum_age, var(age) var_age from student; 2、 日期时间函数 select dateAdd(day, 3, getDate());--加天 select dateAdd(year, 3, getDate());--加年 select dateAdd(hour, 3, getDate());--加小时 --返回跨两个指定日期的日期边界数和时间边界数 select dateDiff(day, '2011-06-20', getDate()); --相差秒数 select dateDiff(second, '2011-06-22 11:00:00', getDate()); --相差小时数 select dateDiff(hour, '2011-06-22 10:00:00', getDate()); select dateName(month, getDate());--当前月份 select dateName(minute, getDate());--当前分钟 select dateName(weekday, getDate());--当前星期 select datePart(month, getDate());--当前月份 select datePart(weekday, getDate());--当前星期 select datePart(second, getDate());--当前秒数 select day(getDate());--返回当前日期天数 select day('2011-06-30');--返回当前日期天数 select month(getDate());--返回当前日期月份 select month('2011-11-10'); select year(getDate());--返回当前日期年份 select year('2010-11-10'); select getDate();--当前系统日期 select getUTCDate();--utc日期 3、 数学函数 select pi();--PI函数 select rand(100), rand(50), rand(), rand();--随机数 select round(rand(), 3), round(rand(100), 5);--精确小数位 --精确位数,负数表示小数点前 select round(123.456, 2), round(254.124, -2); select round(123.4567, 1, 2);
目录 前言 1. 翻译说明 2. 版权声明 1. Hibernate入门 1.1. 前言 1.2. 第一部分 - 第一个Hibernate应用程序 1.2.1. 第一个class 1.2.2. 映射文件 1.2.3. Hibernate配置 1.2.4. 用Ant构建 1.2.5. 启动和辅助类 1.2.6. 加载并存储对象 1.3. 第二部分 - 关联映射 1.3.1. 映射Person类 1.3.2. 单向Set-based的关联 1.3.3. 使关联工作 1.3.4. 值类型的集合 1.3.5. 双向关联 1.3.6. 使双向连起来 1.4. 第三部分 - EventManager web应用程序 1.4.1. 编基本的servlet 1.4.2. 处理与渲染 1.4.3. 部署与测试 1.5. 总结 2. 体系结构(Architecture) 2.1. 概况(Overview) 2.2. 实例状态 2.3. JMX整合 2.4. 对JCA的支持 2.5. 上下文相关的(Contextual)Session 3. 配置 3.1. 可编程的配置方式 3.2. 获得SessionFactory 3.3. JDBC连接 3.4. 可选的配置属性 3.4.1. SQL方言 3.4.2. 外连接抓取(Outer Join Fetching) 3.4.3. 二进制流 (Binary Streams) 3.4.4. 二级缓存与查询缓存 3.4.5. 查询语言的替换 3.4.6. Hibernate的统计(statistics)机制 3.5. 日志 3.6. 实现NamingStrategy 3.7. XML配置文件 3.8. J2EE应用程序服务器的集成 3.8.1. 事务策略配置 3.8.2. JNDI绑定的SessionFactory 3.8.3. 在JTA环境下使用Current Session context (当前session上下文)管理 3.8.4. JMX部署 4. 持久化类(Persistent Classes) 4.1. 一个简单的POJO例子 4.1.1. 实现一个默认的(即无参数的)构造方法(constructor) 4.1.2. 提供一个标识属性(identifier property)(可选) 4.1.3. 使用非final的类 (可选) 4.1.4. 为持久化字段声明访问器(accessors)和是否可变的标志(mutators)(可选) 4.2. 实现继承(Inheritance) 4.3. 实现equals()和hashCode() 4.4. 动态模型(Dynamic models) 4.5. 元组片断映射(Tuplizers) 5. 对象/关系数据库映射基础(Basic O/R Mapping) 5.1. 映射定义(Mapping declaration) 5.1.1. Doctype 5.1.2. hibernate-mapping 5.1.3. class 5.1.4. id 5.1.5. composite-id 5.1.6. 鉴别器(discriminator) 5.1.7. 版本(version)(可选) 5.1.8. timestamp (可选) 5.1.9. property 5.1.10. 多对一(many-to-one) 5.1.11. 一对一 5.1.12. 自然ID(natural-id) 5.1.13. 组件(component), 动态组件(dynamic-component) 5.1.14. properties 5.1.15. 子类(subclass) 5.1.16. 连接的子类(joined-subclass) 5.1.17. 联合子类(union-subclass) 5.1.18. 连接(join) 5.1.19. 键(key) 5.1.20. 字段和规则元素(column and formula elements) 5.1.21. 引用(import) 5.1.22. any 5.2. Hibernate 的类型 5.2.1. 实体(Entities)和值(values) 5.2.2. 基本值类型 5.2.3. 自定义值类型 5.3. 多次映射同一个类 5.4. SQL引号包围的标识符 5.5. 其他元数据(Metadata) 5.5.1. 使用 XDoclet 标记 5.5.2. 使用 JDK 5.0 的注解(Annotation) 5.6. 数据库生成属性(Generat
### 回答1: 在SQL语句,`WHERE` 和 `ON` 都是用于过滤查询结果的条件语句。但它们两个的使用场景不同,在不同的情况下应该使用不同的语句。 `WHERE` 语句用于过滤单表查询的结果,即从单个表筛选数据。例如: ``` SELECT * FROM table_name WHERE column_name = value; ``` `ON` 语句则是在使用连接查询(如 `INNER JOIN` 或 `LEFT JOIN`)时使用的条件语句,用于确定哪些行在两个表之间进行连接。例如: ``` SELECT * FROM table1 INNER JOIN table2 ON table1.column_name = table2.column_name; ``` 因此,总的来说,`WHERE` 语句适用于过滤单表查询的结果,而 `ON` 语句则是在使用连接查询时用于确定连接行的条件语句。 ### 回答2: 在SQL,WHERE 和 ON 都是用来在查询过滤数据的关键字,但它们的使用场景和功能有所不同。 WHERE: WHERE子句用于在SELECT、UPDATE和DELETE语句,通过逻辑条件过滤出满足要求的数据行。它通常在FROM子句之后、GROUP BY子句之前使用。WHERE条件用于从表选择具有特定属性或满足特定条件的行。在WHERE子句,可以使用比较运算符、逻辑运算符和其他条件来定义过滤规则。 示例:SELECT * FROM 表名 WHERE 条件; ON:ON子句主要用于连接两个或多个表进行联接查询。它通常在FROM子句之后、JOIN子句之前使用。ON条件指定了表与表之间的关联条件,用于在连接操作时指定如何将两个表关联在一起。ON条件是在JOIN操作使用的,并指定连接操作所基于的列。 示例:SELECT * FROM 表1 JOIN 表2 ON 表1.列名 = 表2.列名; 总结: - WHERE子句用于在查询结果过滤行,取决于表的数据; - ON子句用于在连接操作指定关联条件,连接两个或多个表。 这两者的不同之处在于: - WHERE 是对从单个表选择行进行过滤; - ON 则是在连接操作时,将多个表的数据进行关联。 通过这两个关键字,我们可以有效地查询和过滤出我们所需的数据。 ### 回答3: 在SQL,"WHERE"和"ON"是用来过滤或连接数据的两种关键字,它们具有不同的作用和使用场景。 "WHERE"子句用于在查询过程筛选出符合特定条件的记录。当我们需要对表的数据进行条件过滤时,使用"WHERE"来指定条件。例如,我们可以使用"WHERE"来选择特定日期范围内的销售记录或者某个状态下的订单。"WHERE"通常出现在"SELECT"语句之后,"FROM"语句之前。 "ON"子句则用于在查询过程连接两个或多个表,它通常用于"JOIN"操作。它用于指定两个表之间的连接条件,通过匹配这些条件来合并相关的行。"ON"通常出现在"JOIN"语句之后,指定连接条件。例如,我们可以使用"ON"来连接两个表的共同列,根据这些列的匹配结果获取相关的数据。 区别在于,"WHERE"是用于筛选行的,而"ON"是用于连接表的。"WHERE"用于对单个表的数据进行条件过滤,而"ON"用于连接多个表并确定它们之间的关系。"WHERE"通常使用在"SELECT"语句,而"ON"通常使用在"JOIN"操作。 总结起来,"WHERE"和"ON"在SQL查询具有不同的作用和用途。"WHERE"用于过滤行,而"ON"用于连接表。它们的区别在于它们操作的对象(行还是表)以及它们的使用位置("WHERE"在"FROM"之后,"ON"在"JOIN"之后)。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值