性能比较:全外连接vs Union,Union All

时间:2011-06-17 07:34:31

标签: sql sql-server-2008 union full-outer-join

我有名为:

的表
mktActualsales (SaleID, EmployeeID, PeriodID,PositionID)
 mktActualSalesItems(SaleItemID, saleID, Item, Quantity)
 mktSalesTargets(TargetID, EmployeeID, PeriodID,PositionID)
 mktSalesTargetItems(TargetITemID, TargetID,ItemID, Quantity )
 sysPeriods(PeriodID, StartDate, EndDate) 

上述表格之间的关系很明显销售和销售详情通过SaleID相关,Target和TargetDetail通过TargetID相关联。我想要展示的是员工在所有时期的销售和目标。有些期间销售缺失,而在其他时期可能缺少目标。

我这样做的计划(到目前为止)是在一个子查询中使用sale和saleDetail的内部联接,在另一个子查询中使用target和targetDetail,然后在两个子查询中使用完全外部联接来获取我需要的数据。但结果非常缓慢。我能做些什么来加快表现。我已经用Google搜索了全外连接和联合之间的性能比较,但没有任何运气。目前我不知道是否可以使用Union / Union All实现我想要的结果。

修改

这是我到目前为止的查询。同时编辑了表格

SELECT  sale.ActualSaleID, 
        COALESCE (sale.EmployeeID, saleTarget.EmployeeID) AS EmployeeID, 
        COALESCE (sale.PositionID, saleTarget.PositionID) AS PositionID, 
        COALESCE (sale.PeriodID, saleTarget.PeriodID) AS PeriodID, 
        COALESCE (sale.SKUID, saleTarget.SKUID) AS SKUID, 
        COALESCE (sale.SalesQuantity, 0) AS SalesQuantity, 
        saleTarget.SalesTargetID, 
        COALESCE (saleTarget.TargetQuantity, 0) AS TargetQuantity, 
        saleTarget.SalesTargetItemID, 
        sale.ActualSaleItemID, 
        p.StartDate, 
        p.EndDate
FROM (
        SELECT  s.ActualSaleID, 
                s.EmployeeID, 
                s.PeriodID, 
                s.PositionID, 
                si.ActualSaleItemID, 
                si.SKUID, 
                si.SalesQuantity
        FROM dbo.mktActualSaleItems AS si 
            INNER JOIN dbo.mktActualSales AS s 
                ON si.ActualSaleID = s.ActualSaleID
    ) AS sale 
    FULL OUTER JOIN
    (
        SELECT  t.EmployeeID, 
                t.PeriodID, 
                t.PositionID, 
                t.SalesTargetID, 
                ti.SKUID, 
                ti.TargetQuantity, 
                ti.SalesTargetItemID
        FROM dbo.mktSalesTargetItems AS ti 
            INNER JOIN dbo.mktSalesTargets AS t 
                ON t.SalesTargetID = ti.SalesTargetID
    ) AS saleTarget 
        ON sale.PeriodID = saleTarget.PeriodID 
        AND sale.PositionID = saleTarget.PositionID 
        AND sale.SKUID = saleTarget.SKUID 
    INNER JOIN dbo.sysPeriods AS p 
        ON p.PeriodID = COALESCE (sale.PeriodID, saleTarget.PeriodID)

2 个答案:

答案 0 :(得分:1)

我认为你不需要子查询,你可以在一个查询中做同样的事情

SELECT  s.ActualSaleID, 
        COALESCE (s.EmployeeID, t.EmployeeID) AS EmployeeID, 
        COALESCE (s.PositionID, t.PositionID) AS PositionID, 
        COALESCE (s.PeriodID, t.PeriodID) AS PeriodID, 
        COALESCE (si.SKUID, ti.SKUID) AS SKUID, 
        COALESCE (si.Quantity, 0) AS SalesQuantity, 
        t.TargetID, 
        COALESCE (ti.Quantity, 0) AS TargetQuantity, 
        ti.TargetITemID, 
        si.SaleItemID, 
        p.StartDate, 
        p.EndDate
FROM dbo.mktActualSales AS s 
        INNER JOIN dbo.mktActualSaleItems AS si 
            ON si.ActualSaleID = s.ActualSaleID
    FULL OUTER JOIN dbo.mktSalesTargets AS t 
        ON s.PeriodID = t.PeriodID 
        AND s.PositionID = t.PositionID 
        AND si.SKUID = ti.SKUID 
            INNER JOIN dbo.mktSalesTargetItems AS ti 
                ON t.SalesTargetID = ti.SalesTargetID
    INNER JOIN dbo.sysPeriods AS p 
        ON p.PeriodID = COALESCE (s.PeriodID, t.PeriodID)

我不确定命名字段,但是你明白了。

这可能会加快查询速度。

不要忘记检查索引!!

答案 1 :(得分:1)

我认为您的查询中存在错误 - 您在SALE和SALETARGET之间的联接不包含employeeID列。 COALESCE隐藏了这一点,但我认为你得到的行数比你需要的多得多......

然而,加快查询速度的方法是先弄清楚它们为什么会变慢;执行计划是要走的路。使用查询分析器告诉您发生了什么 - 您是否正在为所有连接命中索引?如果您已用尽当前实现的所有选项,则仅重写查询以使用union语句。

作为一种风格问题,我认为不应该在你加入的列上使用COALESCE - 它们首先永远不会为空,并且它往往会隐藏错误。