如何将其重写为嵌套查询?

时间:2012-04-11 13:42:30

标签: sql sql-server sql-server-2008-r2

我被告知要使用嵌套查询重写以下查询,而不使用连接以获得更好的性能。这是真的吗?如果是这样,如何重写它?

SELECT distinct A.Company_Name,C.Outlet_Name,
       C.Outlet_FCE_ID,D.Usergroup_Name
FROM   company A, PURCHASE_INVOICE B, 
       Outlet C, User_Group D,CT_USER E
WHERE A.Company_ID = B.Company_ID AND B.Outlet_ID  = C.Outlet_ID 
  AND B.Company_ID = C.Company_ID AND B.Username   = E.Username 
  AND E.Usergroup_ID=D.Usergroup_ID

这是表结构。

enter image description here

2 个答案:

答案 0 :(得分:1)

优化器应该正确,但您可能希望将原始查询的性能与此对比:

select distinct 
    c.company_name, 
    o.outlet_name, 
    o.outlet_fce_id, 
    ug.usergroup_name
from company c 
    inner join (select distinct company_id, outlet_id, username from purchase_invoice) i on c.company_id=i.company_id
    inner join outlet o 
        on  i.outlet_id  = o.outlet_id
        and i.company_id = o.company_id
    inner join ot_user u     on b.username     = e.username
    inner join user_group ug on u.usergroup_id = d.usergroup_id

在追求表上的独特可以消除一些工作,但我怀疑是否会有那么多的欺骗。

purchase_invoice (username, outlet_id, company_id)的索引有什么帮助。这可以加快速度,因为桌子上会是covering index。连接只需查看索引,可以跳过读取实际表。如果桌子很宽,这会有所帮助。

还要注意索引中列的顺序。我猜测ct_user也有很多行,并且它在Username上有一个聚簇索引。这样,索引和ct_user都将按用户名排序,允许merge join加入两个大表。

另外,请为您的表使用连接语法和有意义的别名,例如c fr company和ug for user_group。它应该对数据库无关紧要,但它可以帮助人们尝试阅读您的代码。 此外,allcaps一直看起来像你的尖叫,但也许这只是我: - )

GJ

答案 1 :(得分:0)

让我回答我自己的问题。我不喜欢这样,但我们走了......

    SELECT  distinct
        ( SELECT    Company_Name
          FROM      dbo.COMPANY
          WHERE     Company_ID = p.Company_ID
        ) AS 'CompanyName' ,
        ( SELECT    Outlet_Name
          FROM      dbo.OUTLET
          WHERE     Company_ID = p.Company_ID
                    AND Outlet_ID = p.Outlet_ID
        ) AS 'OutletName' ,
        ( SELECT    Outlet_FCE_ID
          FROM      dbo.OUTLET
          WHERE     Company_ID = p.Company_ID
                    AND Outlet_ID = p.Outlet_ID
        ) 'OutletFCEID' ,
        ( SELECT    Usergroup_Name
          FROM      dbo.USER_GROUP
          WHERE     Usergroup_ID IN ( SELECT    Usergroup_ID
                                      FROM      CT_USER
                                      WHERE     Username = p.UserName )
        ) 'UsergroupName'
FROM    dbo.PURCHASE_INVOICE p