T-SQL语句的几种写法
2010-09-29 10:33
141 查看
T-SQL允许你使用不同的方法解决一个问题.有的时候,尽管选择不是那么明显,但是却可以让你得到令人满意的和快乐的惊奇.下边让我们解读几个例子.可能我们可以在那些不同的方法之中发现一些珍贵的东西.
让我们以我们的老朋友Northwind数据库为例,这里我们用到的是[order details]表,这个表是一个定单的明细表,和order表是多对一的关系.也就是一个定单对应多个订购的产品.假设你想得到每个定单订购的总价值, 但是不包括59号产品.Listing 1给了我们第一种解法:
上边的语句很简单,它排除掉了59号产品的定单明细条目,然后进行分组统计.但是如果我们需要忽略掉订购59号产品的定单呢?也就是说我们要统计没有包含59号产品的定单的价值.你想到了WHERE, NOT EXIST(S)关键词了吗?Listing 2给了我们第二种方法:
如果你不喜欢用exist的话,你可以转化成使用not in:
Listing 3
尽管Listing 1不满足我们现在的查询条件.但是从性能发面考虑,Listing 1还是最好的,因为它只用到了一次表的扫描.而后边的两个查询都是用到了相关子查询,如果你查看查询计划就回看到,他们都涉及到了两次表的扫描.如果你曾经在T-SQL用过交叉表查询的话,你就不会对聚集函数里边的case结构陌生.现在我们就把这个非常有趣的方法应用到我们的问题中来:
Listing 4
HAVING子句起到了对分组的结果进行过滤的作用.如果没有包含59号产品,就会出现0=0,显然这是满足条件的.如果包含了59号产品的订购,就会出现n=0(n<>0),这样的定单就回被过滤掉.查看执行计划你就回发现是一次表的扫描,非常棒!
再来举一个例子:我们这回用到的表是order表,假设我们要统计只通过一个雇员雇员下定单的顾客.你可以想到用子查询not exist来实现:listing5
同样的,这个语句可以通过带有HAVING子句的分组来实现.Listing 6
另一种方法: Listing 7
Listing 6和Listing 7查询消耗都要小于Listing 5.相比Listing 5的两次表扫描,他们只进行一次表的扫描.而Listing 6的损耗还要稍微小于Listing 7.但是,Listing 7的一个显著的特点就是它可以适应到一个顾客对应两个雇员,三个雇员......
这篇文章就是教我们怎么用having子句来达到过滤组的目的.可以达到避免两次表扫描的目的.可以达到更高的性能.(
让我们以我们的老朋友Northwind数据库为例,这里我们用到的是[order details]表,这个表是一个定单的明细表,和order表是多对一的关系.也就是一个定单对应多个订购的产品.假设你想得到每个定单订购的总价值, 但是不包括59号产品.Listing 1给了我们第一种解法:
select OrderID,sum (Quantity * UnitPrice) value from [Order Details] o1 where ProductID <> 59 group by OrderID |
select o1.OrderID,sum (o1.Quantity * o1.UnitPrice) value from [Order Details] o1 where not exists (select * from [Order Details] o2 where o2.OrderID = o1.OrderID and o2.ProductID = 59 ) group by o1.OrderID |
Listing 3
select o1.OrderID,sum (o1.Quantity * o1.UnitPrice) value from [Order Details] o1 where 59 not in ( select ProductID from [Order Details] o2 where o2.OrderID = o1.OrderID ) group by o1.OrderID |
Listing 4
select OrderID,sum (Quantity * UnitPrice) value from [Order Details] o1 group by OrderID having sum (case when ProductID = 59 then 1 else 0 end) = 0 |
再来举一个例子:我们这回用到的表是order表,假设我们要统计只通过一个雇员雇员下定单的顾客.你可以想到用子查询not exist来实现:listing5
select distinct o1.CustomerID from Orders o1 where not exists ( select * from Orders o2 where o2.CustomerID = o1.CustomerID and o2.EmployeeID <> o1.EmployeeID ) |
select CustomerID from Orders group by CustomerID having min (EmployeeID) = max (EmployeeID) |
select CustomerID from Orders group by CustomerID having count (distinct EmployeeID) = 1 |
这篇文章就是教我们怎么用having子句来达到过滤组的目的.可以达到避免两次表扫描的目的.可以达到更高的性能.(
相关文章推荐
- 常用几种数据库,取前10条记录的sql语句写法
- 常用几种数据库,取前10条记录的sql语句写法
- 常用几种数据库,取前10条记录的sql语句写法
- 常用几种数据库,取前10条记录的sql语句写法
- 几种常见复合sql查询语句的linq写法[继续补充中]
- 几种SQL语句的写法
- 几种常见复合sql查询语句的linq写法[继续补充中]
- 分享SQL语句从M条数据读取到N条的几种写法!
- 几种t_sql语句写法
- 常用几种数据库,取前10条记录的sql语句写法
- 三表左连接查询的sql语句写法
- 在SQL SERVER中查询数据库中第几条至第几条之间的数据SQL语句写法
- 整理最近新学到的几种sql写法(一)动态“循环”更新表内数据
- T-SQL 判断字段是否存在的SQL语句写法
- 列表上移下移的SQL语句(mybatis mapper.xml写法)
- MS SQL Server将数据导出Insert语句的几种方案
- C#中产生SQL语句的几种方式
- 分享高性能批量插入和批量删除sql语句写法
- MySQL中使用sql语句插入日期时间类型的写法
- mysql中使用sql语句插入日期时间类型的写法