3

先日、SQL Server でクエリを作成していて、クエリに追加された列の合計を取得する必要がありました。

ここで、合計列を追加する必要があったクエリには、既に約 20 の選択された列がありました。

合計 (集計関数) を機能させるには、GROUP BY事前に選択した列ごとに追加する必要がありました。

これは、非常に退屈で退屈な作業になりました (以下のクエリを参照してください)。1 つの列の SUM を機能させるためだけに、クエリに約 50 行の新しい行を追加する必要がありました。

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 ステートメントに簡単に結合できるローカライズされたスポットに集計を分離する 2 つの方法です。

相関/同期サブクエリの例:

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

私は2つの提案があります

1)データベースにビューを追加します。このビューは、「計算された」列と必要なその他の列で構成されています。計算された列は、クエリからの列をすべての結合で連結した結果です。たとえば、「SELECT CONCAT(col1、col2)、col3 FROM x JOIN y ...z...」

これをマテリアライズド・ビューにすることができます。これにより、ディスクに保存されるため、パフォーマンスが向上します。そしてそれによってあなたはその場で参加することを避けます。

2)そもそも、すべてのフィールドでグループ化しないようにしてください。たとえば、合計が必要な各行に固有のものを見つけます。たぶん、これらすべてのフィールドを返す必要はありません。そして、そうする場合は、それらをグループ化することから始めて、後でテーブルと結合して、必要な列を返すことができます。

編集:サブクエリが良い方法であるというFredSobotkaに同意します。しかし、それはあなたのデータがどのように見えるかに依存します。一般に、特にデータセットが大きい場合は、結合の数を制限するようにしてください。結合は遅くなる傾向があります。

于 2012-09-18T22:58:37.920 に答える