2012-09-18 112 views
2

我前幾天在SQL Server中編寫查詢,並且必須獲得添加到查詢中的列的總和。現在SQL Server:長查詢中的聚合函數和GROUP BY

,我不得不添加之列的查詢已經有大約20選中的列。

爲了使之和(合計功能)工作,我不得不添加GROUP BY針對每個預先選定的列。

這最終成爲一種極其乏味和枯燥的任務(請參閱下面的查詢)。我不得不在查詢中添加大約50個新行,只是爲了讓一列的SUM工作。

有沒有辦法使用SQL Server Management Studio自動編寫這樣的查詢?

這是與其他數據庫一樣(如PL/SQL,Oracle,MySQL等?)

這是查詢的樣子。

SELECT 
     mvLogisticContracts.[mvLogisticContract_id] 
     ,mvLogisticContracts.[CONTRACTNUMBER] 
     ,mvLogisticContracts.[CUSTNMBR] 
     ,mvLogisticContracts.[DateCreated] 
     ,mvLogisticContracts.[TruckAllocatedTotal]  ,mvLogisticContracts.[mvLOgisticAddress_id_StartOriginal] 
      ,mvLogisticContracts.[mvLogisticAddress_id_StartOriginal]  ,mvLogisticContractLineItems.[LineItemQuantity]  ,mvLogisticContractLineItems.[LineItemNo] 
      ,mvLogisticContractLineItems.[OffloadRequired] 
      ,mvLogisticContractLineItems.[CarrierRequested]  ,mvLogisticContractLineItems.[RequestedSerialNo] 
      ,mvLogisticContractLineItems.[mvLogisticAddress_id_Start] 
      ,mvLogisticContractLineItems.[DateReadyBy]  ,mvLogisticContractLineItems.[DateCustomerRequested], 
      mvLogisticContractLineItems.[mvLogisticContractLineItem_id] 
     ,mvLogisticSalespersons.[FirstName],mvLogisticSalespersons.[LastName], 
     mvLogisticServiceTypes.ServiceType, 
     mvLogisticStatuses.Description, 
     mvLogisticSKUs.[SKU],  mvLogisticSKUs.[Length], 
     a1.CITY as \"CityStart\", a1.AddressName as \"AddressNameStart\", a1.Address1 as \"Address1Start\", a1.STATE as \"StateStart\", a1.ZIP as \"ZipStart\", 
     a2.CITY as \"CityEnd\", a2.AddressName as \"AddressNameEnd\", a2.Address1 as \"Address1End\", a2.STATE as \"StateEnd\", a2.ZIP as \"ZipEnd\", 
     mvLogisticContracts.[mvLogisticAddress_id_Start] AS aa1, 
     mvLogisticContracts.[mvLogisticAddress_id_End] AS aa2, 
     SUM(mvLogisticReleases.ReleaseQuantity) as ReleaseQtySum 
      FROM mvLogisticContractLineItems 
      LEFT JOIN mvLogisticContracts ON mvLogisticContractLineItems.mvLogisticContract_id = mvLogisticContracts.mvLogisticContract_id 
      LEFT JOIN mvLogisticSalespersons ON mvLogisticContracts.[mvLogisticSalesperson_id] = mvLogisticSalespersons.[mvLogisticSalesperson_id] 
      LEFT JOIN mvLogisticServiceTypes ON mvLogisticContractLineItems.mvLogisticServiceType_id = mvLogisticServiceTypes.mvLogisticServiceType_id 
      LEFT JOIN mvLogisticStatuses ON mvLogisticContractLineItems.mvLogisticStatus_id = mvLogisticStatuses.mvLogisticStatus_id 
      LEFT JOIN mvLogisticSKUs ON mvLogisticContractLineItems.[SKU_id] = mvLogisticSKUs.[SKU_id] 
      LEFT JOIN mvLogisticAddresses a1 ON a1.[mvLogisticAddress_id] = mvLogisticContractLineItems.[mvLogisticAddress_id_Start] 
      LEFT JOIN mvLogisticAddresses a2 ON a2.[mvLogisticAddress_id] = mvLogisticContractLineItems.[mvLogisticAddress_id_End] 
      /*LEFT JOIN mvLogisticAddresses a1 ON a1.[mvLogisticAddress_id] = mvLogisticContracts.[mvLogisticAddress_id_Start] 
      LEFT JOIN mvLogisticAddresses a2 ON a2.[mvLogisticAddress_id] = mvLogisticContracts.[mvLogisticAddress_id_End]*/ 
      LEFT JOIN mvLogisticReleases ON mvLogisticContractLineItems.mvLogisticContractLineItem_id = mvLogisticReleases.mvLogisticContractLineItem_id 
      GROUP BY 
      mvLogisticContracts.[mvLogisticContract_id] 
     ,mvLogisticContracts.[CONTRACTNUMBER] 
     ,mvLogisticContracts.[CUSTNMBR] 
     ,mvLogisticContracts.[DateCreated] 
     ,mvLogisticContracts.[TruckAllocatedTotal]  ,mvLogisticContracts.[mvLOgisticAddress_id_StartOriginal] 
      ,mvLogisticContracts.[mvLogisticAddress_id_StartOriginal]  ,mvLogisticContractLineItems.[LineItemQuantity]  ,mvLogisticContractLineItems.[LineItemNo] 
      ,mvLogisticContractLineItems.[OffloadRequired] 
      ,mvLogisticContractLineItems.[CarrierRequested]  ,mvLogisticContractLineItems.[RequestedSerialNo] 
      ,mvLogisticContractLineItems.[mvLogisticAddress_id_Start] 
      ,mvLogisticContractLineItems.[DateReadyBy]  ,mvLogisticContractLineItems.[DateCustomerRequested], 
      mvLogisticContractLineItems.[mvLogisticContractLineItem_id] 
     ,mvLogisticSalespersons.[FirstName],mvLogisticSalespersons.[LastName], 
     mvLogisticServiceTypes.ServiceType, 
     mvLogisticStatuses.Description, 
     mvLogisticSKUs.[SKU],  
     mvLogisticSKUs.[Length], 
     a1.CITY, a1.AddressName, a1.Address1, a1.STATE, a1.ZIP, 
     a2.CITY, a2.AddressName, a2.Address1, a2.STATE, a2.ZIP, 
     mvLogisticContracts.[mvLogisticAddress_id_Start], 
     mvLogisticContracts.[mvLogisticAddress_id_End] 

回答

7

子查詢和公用表表達式(CTE)是兩種方法將聚合分離到易於加入主SELECT語句的本地化點。

相關/同步的子查詢例如:

SELECT c.contract_id, c.contractnum, c.customernum, 
    (SELECT SUM(li.price * li.orderquantity) 
    FROM lineitems li 
    WHERE li.contract_id = c.contract_id 
    ) AS grand_total 
FROM contracts c 
WHERE ... 

引用在SELECT列表中的相關子查詢是帶回一個值的便捷方法。

加入到CTE:

WITH ordersummary AS 
(SELECT li.contract_id, 
     COUNT(DISTINCT li.partnum) AS distinctproducts, 
     SUM(li.orderquantity) AS itemcount, 
     SUM(li.price * li.orderquantity) AS totalprice, 
     MIN(p.ship_ready_date) AS earliest_partial_ship_date, 
     MAX(p.ship_ready_date) AS earliest_complete_ship_date 
     FROM lineitems li 
     INNER JOIN parts p 
      ON p.partnum = li.partnum 
     GROUP BY li.contract_id 
) 
SELECT c.contract_id, c.contractnum, c.customernum, 
s.distinctproducts, s.itemcount, s.totalprice, 
s.earliest_partial_ship_date, s.earliest_complete_ship_date 
FROM contracts c 
INNER JOIN ordersummary s 
ON s.contract_id = c.contract_id 
WHERE ... 

加入到一個表達式:

SELECT c.contract_id, c.contractnum, c.customernum, 
s.distinctproducts, s.itemcount, s.totalprice, 
s.earliest_partial_ship_date, s.earliest_complete_ship_date 
FROM contracts c 
INNER JOIN 
(SELECT li.contract_id, 
     COUNT(DISTINCT li.partnum) AS distinctproducts, 
     SUM(li.orderquantity) AS itemcount, 
     SUM(li.price * li.orderquantity) AS totalprice, 
     MIN(p.ship_ready_date) AS earliest_partial_ship_date, 
     MAX(p.ship_ready_date) AS earliest_complete_ship_date 
     FROM lineitems li 
     INNER JOIN parts p 
      ON p.partnum = li.partnum 
     GROUP BY li.contract_id 
) AS s 
ON s.contract_id = c.contract_id 
WHERE ... 
+0

編輯:我想我找到了我在找的東西(通過使用你提到的子查詢); http://pastebin.com/LjWyCgak。非常感謝。 – Tool

+0

我已經添加了一些使用表格表達式的示例,這些示例使您可以一次檢索多個列。 –

+1

如果這回答了您的問題,您應該將其標記爲「已接受」,以便其他人也可以從中學習。 –

1

我有兩個建議

1)視圖添加到數據庫中。該視圖由您需要的「計算」列和其他列組成。計算列是將查詢中的所有列連接在一起並將其與所有連接連接起來的結果。例如「SELECT CONCAT(col1,col2),col3 FROM x JOIN y ... z ...」

您可以將其設置爲物化視圖,該視圖將其保存在磁盤上後會有更好的性能。從而避免加入進來。

2)儘量避免將所有字段分組在一起。例如,找出每一行的獨特之處,你需要總和。也許你不需要返回所有這些字段。如果你這樣做,你可以先將它們分組,然後加入表格以返回你需要的列。

編輯:我與弗雷德索博特卡同意,子查詢是一個很好的路要走。但這取決於你的數據是什麼樣子。一般來說,您應該嘗試限制連接的數量,特別是如果您有大型數據集。聯接往往很慢。

+0

我想我通過更改查詢來解決它:http://pastebin.com/m2ArmxGc – Tool