28

私は何が欠けていますか?

このクエリは、重複したデータを何度も返しています。カウントは完全な合計に対して正しいですが、1 行を期待していますが、値が約 40 回繰り返されています。何か案は?

SELECT BrandId
      ,SUM(ICount) OVER (PARTITION BY BrandId ) 
  FROM Table 
WHERE DateId  = 20130618

わかった?

BrandId ICount
2       421762
2       421762
2       421762
2       421762
2       421762
2       421762
2       421762
1       133346
1       133346
1       133346
1       133346
1       133346
1       133346
1       133346

私は何が欠けていますか?

クエリ全体が次のようになっているため、パーティションを削除できません。

SELECT BrandId
       ,SUM(ICount) OVER (PARTITION BY BrandId) 
       ,TotalICount= SUM(ICount) OVER ()    
        ,SUM(ICount) OVER () / SUM(ICount) OVER (PARTITION BY BrandId)  as Percentage
FROM Table 
WHERE DateId  = 20130618

これはこれを返します:

BrandId (No column name)    TotalICount Percentage
2       421762              32239892    76
2       421762              32239892    76
2       421762              32239892    76
2       421762              32239892    76
2       421762              32239892    76
2       421762              32239892    76

個別のものを使用しなくても、次のような出力が期待できます。

BrandId (No column name)    TotalICount Percentage
2       421762              32239892    76
9       1238442             32239892    26
10      1467473             32239892    21
4

4 に答える 4

47

私の意見では、OVER() 句で合計するときに SQL で GROUP BY が必要な理由と、BrandID ごとに 1 行が必要な場合にデータ行が繰り返される理由を説明することが重要だと思います。

この例を見てみましょう: 2 つの日付の間で、特定の注文カテゴリごとに、各注文明細行の合計販売価格を集計する必要がありますが、最終結果に個々の注文データを保持する必要もあります。SalesPrice 列に SUM() を使用すると、GROUP BY が必要になるため、正しい合計を取得できず、select ステートメントで個々の注文行を保持できないため、詳細が押しつぶされます。

#temp テーブル、@table 変数、または CTE にデータの合計が入力されてグループ化されていることがよくあります。これにより、必要な合計の列を取得するために後で再度結合できます。これにより、処理時間が長くなり、コード行が増える可能性があります。代わりに、次のように OVER(PARTITION BY ()) を使用します。

SELECT
  OrderLine, 
  OrderDateTime, 
  SalePrice, 
  OrderCategory,
  SUM(SalePrice) OVER(PARTITION BY OrderCategory) AS SaleTotalPerCategory
FROM tblSales 
WHERE OrderDateTime BETWEEN @StartDate AND @EndDate

グループ化しておらず、個々の注文明細列が選択されていることに注意してください。最後の列の PARTITION BY は、各カテゴリのデータの各行の販売価格の合計を返します。最後の列が本質的に言っていることは、結果のパーティションと指定されたカテゴリ(OVER(PARTITION BY CategoryHere))による販売価格(SUM(SalePrice))の合計が必要ということです。

次のように、select ステートメントから他の列を削除し、最後の SUM() 列を残すとします。

SELECT
  SUM(SalePrice) OVER(PARTITION BY OrderCategory) AS SaleTotalPerCategory
FROM tblSales 
WHERE OrderDateTime BETWEEN @StartDate AND @EndDate

結果は、元の結果セットの行ごとにこの合計を繰り返します。その理由は、このメソッドは GROUP BY を必要としないためです。個々の行データを保持する必要がない場合は、OVER() を使用せずに単純に SUM() を実行し、データを適切にグループ化します。繰り返しになりますが、特定の合計を含む追加の列が必要な場合は、追加の選択を行わずに上記の OVER(PARTITION BY ()) メソッドを使用して元に戻すことができます。

上記は純粋に、同じ番号の行が繰り返される理由を説明し、この条項が提供する内容を理解するのに役立ちます。この方法はさまざまな方法で使用できます。次のドキュメントをさらに読むことを強くお勧めします。

オーバー条項

于 2014-12-20T21:43:53.560 に答える
19

部分を使用DISTINCTするか、単に削除して使用することができます:PARTITION BYGROUP BY

SELECT BrandId
       ,SUM(ICount)
       ,TotalICount = SUM(ICount) OVER ()    
       ,Percentage = SUM(ICount) OVER ()*1.0 / SUM(ICount) 
FROM Table 
WHERE DateId  = 20130618
GROUP BY BrandID

合計を BrandID ごとの数で割っている理由がわかりません。それが間違いで、合計の割合が必要な場合は、上記のビットを逆にして次のようにします。

SELECT BrandId
           ,SUM(ICount)
           ,TotalICount = SUM(ICount) OVER ()    
           ,Percentage = SUM(ICount)*1.0 / SUM(ICount) OVER () 
    FROM Table 
    WHERE DateId  = 20130618
    GROUP BY BrandID
于 2013-07-25T20:21:37.593 に答える
14

あなたが望むクエリはこれだと思います:

SELECT BrandId, SUM(ICount),
       SUM(sum(ICount)) over () as TotalCount,
       100.0 * SUM(ICount) / SUM(sum(Icount)) over () as Percentage
FROM Table 
WHERE DateId  = 20130618
group by BrandId;

これは、group byブランドのために行います。そして、「パーセンテージ」を計算します。このバージョンは、0 から 100 までの数値を生成する必要があります。

于 2013-07-25T20:21:34.030 に答える
9

句の削除partition byと追加、group by

SELECT BrandId
      ,SUM(ICount) totalSum
  FROM Table 
WHERE DateId  = 20130618
GROUP BY BrandId
于 2013-07-25T20:11:10.950 に答える