2016-01-20 24 views
0

我希望與利率和他們的差異作爲保證金我們可以在不進行子查詢的情況下對數據進行求和嗎?

相關的合同我想這樣做總和在SQL Server中沒有自我加入子查詢中的表。

我的架構設置如下:

合同

ContractId relatedContractId Discriminator 
----------------------------------------------------- 
8041  8040    VendorContract 
8040  8041    CustomerContract 
8042  NULL    CustomerContract 
8043  8044    CustomerContract 
8044  8043    VendorContract 

價格

RateId RatePerUnit ContractId 
--------------------------------- 
8052 120.00  8041 
8053 123.00  8041 
8050 121.00  8040 
8051 127.00  8040 
8052 120.00  8042 
8053 137.00  8042 
8054 102.00  8043 
8055 100.00  8044 

預期成果是

CContract  VContract Marging 
------------------------------------ 
8040   8041   5.00 
8042   Null   257.00 
8043   8044   2.00 

我已經實現了正確的結果,下面的查詢使用了子查詢,但我需要在不使用子查詢的情況下執行此操作。

SELECT cts.ContractId, 
     cts.RelatedContractId, 
     (ISNULL(SUM(r.RatePerUnit),0) - ISNULL(vr.VendorContractRate,0)) AS Margin 
FROM Contracts cts 
     LEFT OUTER JOIN Contracts vcts 
      ON cts.RelatedContractId = vcts.ContractId 
     LEFT OUTER JOIN Rates r 
      ON cts.ContractId = r.ContractId 
     LEFT OUTER JOIN 
     ( SELECT c.ContractId, 
        ISNULL(SUM(r.RatePerUnit),0) VendorContractRate 
      FROM Contracts c 
        LEFT OUTER JOIN Rates r 
         ON r.ContractId = c.contractId 
      WHERE c.Discriminator = 'VendorContract' 
      GROUP BY c.ContractId 
     ) vr 
      ON cts.RelatedContractId = vr.ContractId   
WHERE cts.Discriminator = 'CustomerContract' 
GROUP BY cts.ContractId, cts.RelatedContractId, vr.VendorContractRate; 

我試圖重寫此查詢,而無需使用子查詢,如下所示:

SELECT vc.ContractId, 
     SUM(r.RatePerUnit), 
     SUM(vr.RatePerUnit) 
FROM Contracts c 
     LEFT OUTER JOIN Contracts vc 
      ON c.RelatedContractId = vc.ContractId 
     LEFT OUTER JOIN Rates r 
      ON r.ContractId= c.ContractId 
     INNER JOIN Rates vr 
      ON vr.ContractId = vc.ContractId 
WHERE c.Discriminator = 'CustomerContract' 
AND  c.ContractStatus = 0 
GROUP BY vc.ContractId; 

不幸的是,這是我的複製結果,所以它是不正確的。對於多種費率,它將費率乘以存在的費率數量。所以我得到的結果是:

CContract  VContract Marging 
------------------------------------ 
8040   8041   10.00  ---- in this case 496-486(248-243) 
8042   Null   514.00  
8043   8044   2.00   
+0

爲什麼你不希望使用子查詢? – GarethD

+0

性能問題。請幫助我沒有子查詢 –

回答

1

我看不出這樣做沒有某種形式的子查詢的簡單方式,但也沒有理由儘量避免子查詢。你已經列舉了希望避免子查詢的性能原因,但這不是一個有效的原因,SQL是一種聲明性語言,即你告訴優化者你想要什麼而不是如何獲得它,所以僅僅因爲你使用了子查詢並不意味着你是改變計劃的必需品。

雖然不需要刪除子查詢來提高性能,但這並不是說您的查詢性能仍然無法提高。這可以通過刪除不必要的連接來完成。下面應該有更好的表現:

WITH SummedRates AS 
( SELECT ContractID, RatePerUnit = SUM(RatePerUnit) 
    FROM Rates 
    GROUP BY ContractID 
) 
SELECT c.ContractID, 
     c.RelatedContractID, 
     Margin = ISNULL(r.RatePerUnit, 0) - ISNULL(r2.RatePerUnit, 0) 
FROM Contracts AS c 
     LEFT JOIN SummedRates AS r 
      ON r.ContractId = c.ContractId 
     LEFT JOIN SummedRates AS r2 
      ON r2.ContractId = c.RelatedContractId 
WHERE c.Discriminator = 'CustomerContract' 

FULL工作演示

DECLARE @Contracts TABLE (ContractId INT, relatedContractId INT, Discriminator VARCHAR(20)); 
INSERT @Contracts (ContractId, relatedContractId, Discriminator) 
VALUES 
    (8041, 8040, 'VendorContract'), 
    (8040, 8041, 'CustomerContract'), 
    (8042, NULL, 'CustomerContract'), 
    (8043, 8044, 'CustomerContract'), 
    (8044, 8043, 'VendorContract'); 

DECLARE @Rates TABLE (RateId INT, RatePerUnit DECIMAL(5, 2), ContractId INT); 
INSERT @Rates (RateId, RatePerUnit, ContractId) 
VALUES 
    (8052, 120.00, 8041), 
    (8053, 123.00, 8041), 
    (8050, 121.00, 8040), 
    (8051, 127.00, 8040), 
    (8052, 120.00, 8042), 
    (8053, 137.00, 8042), 
    (8054, 102.00, 8043), 
    (8055, 100.00, 8044); 

WITH SummedRates AS 
( SELECT ContractID, RatePerUnit = SUM(RatePerUnit) 
    FROM @Rates 
    GROUP BY ContractID 
) 
SELECT c.ContractID, 
     c.RelatedContractID, 
     Margin = ISNULL(r.RatePerUnit, 0) - ISNULL(r2.RatePerUnit, 0) 
FROM @Contracts AS c 
     LEFT JOIN SummedRates AS r 
      ON r.ContractId = c.ContractId 
     LEFT JOIN SummedRates AS r2 
      ON r2.ContractId = c.RelatedContractId 
WHERE c.Discriminator = 'CustomerContract'; 
相關問題