195
    USE AdventureWorks2008R2;
GO
SELECT SalesOrderID, ProductID, OrderQty
    ,SUM(OrderQty) OVER(PARTITION BY SalesOrderID) AS 'Total'
    ,AVG(OrderQty) OVER(PARTITION BY SalesOrderID) AS 'Avg'
    ,COUNT(OrderQty) OVER(PARTITION BY SalesOrderID) AS 'Count'
    ,MIN(OrderQty) OVER(PARTITION BY SalesOrderID) AS 'Min'
    ,MAX(OrderQty) OVER(PARTITION BY SalesOrderID) AS 'Max'
FROM Sales.SalesOrderDetail 
WHERE SalesOrderID IN(43659,43664);

私はその条項について読みましたが、なぜそれが必要なのかわかりません。関数は何をしOverますか?何をしPartitioning Byますか?なぜ私は書くことで質問をすることができないのGroup By SalesOrderIDですか?

4

8 に答える 8

167

使用できますGROUP BY SalesOrderID。違いは、GROUP BY では、GROUP BY に含まれていない列の集計値のみを取得できることです。

対照的に、GROUP BY の代わりにウィンドウ集計関数を使用すると、集計された値と集計されていない値の両方を取得できます。つまり、例のクエリではそれを行っていませんがOrderQty、同じ のグループで個々の値とその合計、カウント、平均などの両方を取得できますSalesOrderID

ウィンドウ化された集計が優れている理由の実際的な例を次に示します。すべての値が合計の何パーセントであるかを計算する必要があるとします。ウィンドウ化された集計がなければ、最初に集計された値のリストを取得し、次にそれを元の行セットに結合する必要があります。つまり、次のようになります。

SELECT
  orig.[Partition],
  orig.Value,
  orig.Value * 100.0 / agg.TotalValue AS ValuePercent
FROM OriginalRowset orig
  INNER JOIN (
    SELECT
      [Partition],
      SUM(Value) AS TotalValue
    FROM OriginalRowset
    GROUP BY [Partition]
  ) agg ON orig.[Partition] = agg.[Partition]

ウィンドウ集計で同じことを行う方法を見てみましょう。

SELECT
  [Partition],
  Value,
  Value * 100.0 / SUM(Value) OVER (PARTITION BY [Partition]) AS ValuePercent
FROM OriginalRowset orig

はるかに簡単でクリーンですね。

于 2011-06-02T19:54:56.120 に答える
76

この句は、を使用するかどうかに関係なくOVER、さまざまな範囲(「ウィンドウ処理」)で集計を行うことができるという点で強力です。GROUP BY

例:あたりSalesOrderIDのカウントとすべてのカウントを取得する

SELECT
    SalesOrderID, ProductID, OrderQty
    ,COUNT(OrderQty) AS 'Count'
    ,COUNT(*) OVER () AS 'CountAll'
FROM Sales.SalesOrderDetail 
WHERE
     SalesOrderID IN(43659,43664)
GROUP BY
     SalesOrderID, ProductID, OrderQty

COUNTのsを取得します、いいえGROUP BY

SELECT
    SalesOrderID, ProductID, OrderQty
    ,COUNT(OrderQty) OVER(PARTITION BY SalesOrderID) AS 'CountQtyPerOrder'
    ,COUNT(OrderQty) OVER(PARTITION BY ProductID) AS 'CountQtyPerProduct',
    ,COUNT(*) OVER () AS 'CountAllAgain'
FROM Sales.SalesOrderDetail 
WHERE
     SalesOrderID IN(43659,43664)
于 2011-06-02T18:59:51.703 に答える
51

SalesOrderID だけを GROUP BY したい場合は、SELECT 句に ProductID 列と OrderQty 列を含めることができません。

PARTITION BY 句を使用すると、集計関数を分割できます。明白で便利な例の 1 つは、注文の注文明細の明細番号を生成する場合です。

SELECT
    O.order_id,
    O.order_date,
    ROW_NUMBER() OVER(PARTITION BY O.order_id) AS line_item_no,
    OL.product_id
FROM
    Orders O
INNER JOIN Order_Lines OL ON OL.order_id = O.order_id

(私の構文は少しずれているかもしれません)

次に、次のようなものが返されます。

order_id    order_date    line_item_no    product_id
--------    ----------    ------------    ----------
    1       2011-05-02         1              5
    1       2011-05-02         2              4
    1       2011-05-02         3              7
    2       2011-05-12         1              8
    2       2011-05-12         2              1
于 2011-06-02T19:01:20.903 に答える
50

例を挙げて説明すると、それがどのように機能するかを見ることができます。

次のテーブル DIM_EQUIPMENT があると仮定します。

VIN         MAKE    MODEL   YEAR    COLOR
-----------------------------------------
1234ASDF    Ford    Taurus  2008    White
1234JKLM    Chevy   Truck   2005    Green
5678ASDF    Ford    Mustang 2008    Yellow

SQL の下で実行

SELECT VIN,
  MAKE,
  MODEL,
  YEAR,
  COLOR ,
  COUNT(*) OVER (PARTITION BY YEAR) AS COUNT2
FROM DIM_EQUIPMENT

結果は以下のようになります

VIN         MAKE    MODEL   YEAR    COLOR     COUNT2
 ----------------------------------------------  
1234JKLM    Chevy   Truck   2005    Green     1
5678ASDF    Ford    Mustang 2008    Yellow    2
1234ASDF    Ford    Taurus  2008    White     2

何が起こったのか見てください。

Group By なしで YEAR と Match with ROW なしでカウントできます。

以下のように WITH 句を使用して同じ結果を得るためのもう 1 つの興味深い方法は、WITH がインライン VIEW として機能し、特に複雑なクエリを簡素化することができます。

 WITH EQ AS
  ( SELECT YEAR AS YEAR2, COUNT(*) AS COUNT2 FROM DIM_EQUIPMENT GROUP BY YEAR
  )
SELECT VIN,
  MAKE,
  MODEL,
  YEAR,
  COLOR,
  COUNT2
FROM DIM_EQUIPMENT,
  EQ
WHERE EQ.YEAR2=DIM_EQUIPMENT.YEAR;
于 2014-05-08T06:37:48.560 に答える
19

PARTITION BY と組み合わせた場合の OVER 句は、クエリの返された行を評価することによって、前の関数呼び出しを分析的に実行する必要があることを示しています。インライン GROUP BY ステートメントと考えてください。

OVER (PARTITION BY SalesOrderID)は、SUM、AVG などの関数について、クエリから返されたレコードのサブセットを介して値を返し、そのサブセットを外部キー SalesOrderID で分割することを示しています。

したがって、各 UNIQUE SalesOrderID のすべての OrderQty レコードを合計し、その列名は「Total」と呼ばれます。

これは、複数のインライン ビューを使用して同じ情報を見つけるよりもはるかに効率的な手段です。このクエリをインライン ビュー内に配置し、Total でフィルター処理できます。

SELECT ...,
FROM (your query) inlineview
WHERE Total < 200
于 2011-06-02T19:01:05.927 に答える
4
  • Query Petition条項とも呼ばれます。
  • Group By条項に類似

    • データをチャンク (またはパーティション) に分割する
    • パーティション境界で区切る
    • 関数はパーティション内で実行されます
    • パーティング境界を越えると再初期化される

構文:
関数 (...) OVER (PARTITION BY col1 col3,...)

  • 機能

    • COUNT()SUM()MIN()MAX()などの使い慣れた関数
    • 新機能も (例: ROW_NUMBER()RATION_TO_REOIRT()など)


例の詳細: http://msdn.microsoft.com/en-us/library/ms189461.aspx

于 2014-10-20T17:39:39.610 に答える
-4
prkey   whatsthat               cash   
890    "abb                "   32  32
43     "abbz               "   2   34
4      "bttu               "   1   35
45     "gasstuff           "   2   37
545    "gasz               "   5   42
80009  "hoo                "   9   51
2321   "ibm                "   1   52
998    "krk                "   2   54
42     "kx-5010            "   2   56
32     "lto                "   4   60
543    "mp                 "   5   65
465    "multipower         "   2   67
455    "O.N.               "   1   68
7887   "prem               "   7   75
434    "puma               "   3   78
23     "retractble         "   3   81
242    "Trujillo's stuff   "   4   85

問い合わせた結果です。ソースとして使用されるテーブルは、最後の列がないことを除いて同じです。この列は、3 番目の列の移動合計です。

クエリ:

SELECT prkey,whatsthat,cash,SUM(cash) over (order by whatsthat)
    FROM public.iuk order by whatsthat,prkey
    ;

(表は public.iuk となります)

sql version:  2012

これは dbase(1986) レベルを少し超えています。完成させるのに 25 年以上の年月が必要だった理由がわかりません。

于 2016-11-17T12:12:42.573 に答える