3

前几天我在 SQL Server 中编写了一个查询,并且必须得到一个添加到查询中的列的总和。

现在,我必须添加 sum 列的查询已经有大约 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]
4

2 回答 2

8

子查询和公用表表达式 (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 ...
于 2012-09-18T22:50:58.090 回答
1

我有两个建议

1) 向数据库添加视图。此视图由“计算”列和您需要的其他列组成。计算列是将查询中的列与所有联接连接在一起的结果。例如“SELECT CONCAT(col1,col2), col3 FROM x JOIN y ... z ...”

您可以将其设为物化视图,这将提供更好的性能,因为它保存在磁盘上。从而避免即时加入。

2)首先尝试避免按所有字段进行分组。例如找出每一行的独特之处,你需要总和。也许您不需要返回所有这些字段。如果您这样做,您可以先将它们分组,然后加入表以返回您需要的列。

编辑:我同意 Fred Sobotka 的观点,即子查询是一个好方法。但这取决于您的数据是什么样的。一般来说,您应该尝试限制连接的数量,尤其是在您拥有大型数据集的情况下。连接往往很慢。

于 2012-09-18T22:58:37.920 回答