先连接后筛选和先筛选后连接问题

gw6328 2011-08-06 02:36:04
1.select * from tb1 a join tb2 b on a.id=b.id
where a.time between t11 and t12 and b.time between t21 and t22

2.select * from (select * from tb1 where time between t11 and t12) a
join (select * from tb2 where time between t21 and t22) b on a.id=b.id

以前遇到一个这种情况的,最初是用的第一种方式,因为一般都想到第一次方式。但是在实际工作中调整时,发现第二种方式更快了。所以改成第二种方式。

基本都是 tb1,tb2表数据大,t1 t2时间段数据少 id与time上有索引。

到底该怎么用?
...全文
1837 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
AcHerat 2011-08-07
  • 打赏
  • 举报
回复
我觉得可能和筛选的时间段有关系,如果筛选出的时间段比较大,数据多,子查询的效率估计没第一种连接查询的效率好,具体的楼主还是看看执行计划来取舍。
yuerjiajia 2011-08-07
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 maco_wang 的回复:]

执行顺序:

1. FROM:对FROM子句中的前两个表执行笛卡尔积,生成虚拟表VT1。

2. ON:对VT1应用ON筛选器。只有那些使<join_condition>为真的行才被插入VT2。

3. OUTER(JOIN):如果指定了OUTER JOIN,保留表中未找到匹配的行将作为外部行添加到VT2,生成VT3。

如果FROM子句包含两个以上的表,则对上一个联接生成的结果……
[/Quote]
如果使用楼主的第二种方式 执行计划还是这样吗?
gw6328 2011-08-06
  • 打赏
  • 举报
回复
周一结贴!
叶子 2011-08-06
  • 打赏
  • 举报
回复
执行顺序:

1. FROM:对FROM子句中的前两个表执行笛卡尔积,生成虚拟表VT1。

2. ON:对VT1应用ON筛选器。只有那些使<join_condition>为真的行才被插入VT2。

3. OUTER(JOIN):如果指定了OUTER JOIN,保留表中未找到匹配的行将作为外部行添加到VT2,生成VT3。

如果FROM子句包含两个以上的表,则对上一个联接生成的结果表和下一个表重复执行步骤1到步骤3,直到

处理完所有的表为止。

4. 对VT3应用WHERE筛选器。只有使<where_condition>为TRUE的行才被插入VT4。

5. GROUP BY:按GROUP BY 子句中的列列表对VT4中的行分组,生成VT5。

6. CUBE|ROLLUP:把超组插入VT5,生成VT6。

7. HAVING:对VT6应用HAVING筛选器。只有使<having_condition>为TRUE的组才会被插入VT7。

8. SELECT:处理SELECT列表,产生VT8。

9. DISTINCT:将重复的行从VT8中移除,产生VT9。

10. ORDER BY:将VT9中的行按ORDER BY子句中的列列表排序,生成一个有表(VC10)。

11. TOP:从VC10的开始处选择指定数量或比例的行,生成表VT11,并返回给调用者。

dovei 2011-08-06
  • 打赏
  • 举报
回复

1.select * from tb1 a join tb2 b on a.id=b.id
where a.time between t11 and t12 and b.time between t21 and t22

2.select * from tb1 a join tb2 b on a.id=b.id and b.time between t21 and t22
where a.time between t11 and t12

LZ试试这二个有没有区别
gw6328 2011-08-06
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 ssp2009 的回复:]

你看执行计划有没有用到索引,08的查询优化器也改进了很多。
[/Quote]
我正在造数据呢。没数据测试 :)
快溜 2011-08-06
  • 打赏
  • 举报
回复
你看执行计划有没有用到索引,08的查询优化器也改进了很多。
gw6328 2011-08-06
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 jinfengyiye 的回复:]

引用 3 楼 ssp2009 的回复:

你看看执行计划,对于数据量大的采用临时表筛选再连接确实快了很多。

我今天遇到的又是第二种快的。
第二种在接连是没有用到id的索引吧。因为多了一层。
所以不知如何取舍!
[/Quote]
这里说错了。是第一种快,所以不知取舍。
gw6328 2011-08-06
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 ssp2009 的回复:]

你看看执行计划,对于数据量大的采用临时表筛选再连接确实快了很多。
[/Quote]
我今天遇到的又是第二种快的。
第二种在接连是没有用到id的索引吧。因为多了一层。
所以不知如何取舍!
快溜 2011-08-06
  • 打赏
  • 举报
回复
你看看执行计划,对于数据量大的采用临时表筛选再连接确实快了很多。
gw6328 2011-08-06
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 ssp2009 的回复:]

实际上你第一种这样写也应该是先筛选后连接
select * from tb1 a join tb2 b on a.id=b.id
and a.time between t11 and t12 and b.time between t21 and t22
[/Quote]
不是吧。这样子是先连接后筛选吧。
快溜 2011-08-06
  • 打赏
  • 举报
回复
实际上你第一种这样写也应该是先筛选后连接
select * from tb1 a join tb2 b on a.id=b.id
and a.time between t11 and t12 and b.time between t21 and t22

22,210

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 疑难问题
社区管理员
  • 疑难问题社区
  • 尘觉
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧