用户操作
[即时聊天] [发私信] [加为好友]
胡亚玺ID:pfworld
13234次访问,排名8728好友6人,关注者13
想来想去还是比较喜欢软件开发!
pfworld的文章
原创 11 篇
翻译 0 篇
转载 27 篇
评论 22 篇
pfworld的公告
辭職了!開始找新的工作!!希望能找到一個真正的做開發的公司!
最近评论
フレンド:セックスフレンド募集セックスフレンド募集セックスフレンド募集セックスセックスフレンド募集セックスフレンド募集セックスフレンド募集セックスwow gold
crm
出会い
……
随风:郁闷,忘留邮箱了
iesix@126.com
随风:可以给我也发一份源码吗?
谢谢楼主啊
文章分类
收藏
    相册
    界面设计
    网海艳图
    C# 网站
    http://www.codeproject.com/(RSS)
    日本語の翻訳のウェブサイト
    金山词霸查词-免费在线词典查词翻译
    存档
    软件项目交易
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    转载 老外对T-sql的研究:一个问题多种方法收藏

    新一篇: 通用Sql Server数据库查询语句精华使用 | 旧一篇: 通用Sql Server数据库查询语句精华使用

    老外对T-sql的研究:一个问题多种方法

    T-SQL允许你使用不同的方法解决一个问题.有的时候,尽管选择不是那么明显,但是却可以让你得到令人满意的和快乐的惊奇.下边让我们解读Dr. Tom Moreau对同一问题不同的可能性的探索.可能我们可以在那些不同的方法之中发现一些珍贵的东西.


    让我们以我们的老朋友Northwind数据库为例,这里我们用到的是[order details]表,这个表是一个定单的明细表,和order表是多对一的关系.也就是一个定单对应多个订购的产品.假设你想得到每个定单订购的总价值,但是不包括59号产品.Listing 1给了我们第一种解法:


    select
    OrderID,sum (Quantity * UnitPrice) value
    from [Order Details] o1 where ProductID <> 59
    group by OrderID

     


    上边的语句很简单,它排除掉了59号产品的定单明细条目,然后进行分组统计.但是如果我们需要忽略掉订购59号产品的定单呢?也就是说我们要统计没有包含59号产品的定单的价值.你想到了WHERE, NOT EXIST(S)关键词了吗?Listing 2给了我们第二种方法:


    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

     


    如果你不喜欢用exist的话,你可以转化成使用not in:


    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 1不满足我们现在的查询条件.但是从性能发面考虑,Listing 1还是最好的,因为它只用到了一次表的扫描.而后边的两个查询都是用到了相关子查询,如果你查看查询计划就回看到,他们都涉及到了两次表的扫描.如果你曾经在 T-SQL用过交叉表查询的话,你就不会对聚集函数里边的case结构陌生.现在我们就把这个非常有趣的方法应用到我们的问题中来:


    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

     


    HAVING子句起到了对分组的结果进行过滤的作用.如果没有包含59号产品,就会出现0=0,显然这是满足条件的.如果包含了59号产品的订购,就会出现n=0(n<>0),这样的定单就回被过滤掉.查看执行计划你就回发现是一次表的扫描,非常棒!


    再来举一个例子:我们这回用到的表是order表,假设我们要统计只通过一个雇员雇员下定单的顾客.你可以想到用子查询not exist来实现:


    select distinct
    o1.CustomerID
    from
    Orders o1
    where not exists
    (
    select * from Orders o2
    where o2.CustomerID = o1.CustomerID
    and o2.EmployeeID <> o1.EmployeeID
    )

     


    同样的,这个语句可以通过带有HAVING子句的分组来实现.

     

    Listing 6

    select CustomerID from
    Orders group by CustomerID
    having
    min (EmployeeID) = max (EmployeeID)

     


    另一种方法:


    Listing 7

    select CustomerID from
    Orders group by CustomerID
    having
    count (distinct EmployeeID) = 1

     

     

    Listing 6和Listing 7查询消耗都要小于Listing 5.相比Listing 5的两次表扫描,他们只进行一次表的扫描.而Listing 6的损耗还要稍微小于Listing 7.但是,Listing 7的一个显著的特点就是它可以适应到一个顾客对应两个雇员,三个雇员......

    其实大家可能现在明白了这篇文章将的是什么?它就是教我们怎么用having 子句来达到过滤组的目的.可以达到避免两次表扫描的目的.可以达到更高的性能.我从这篇文章学到了很多的方法,你呢?

     

    发表于 @ 2007年05月30日 18:01:00|评论(loading...)|编辑

    新一篇: 通用Sql Server数据库查询语句精华使用 | 旧一篇: 通用Sql Server数据库查询语句精华使用

    评论:没有评论。

    发表评论  


    登录
    Csdn Blog version 3.1a
    Copyright © pfworld