Oracleの「Partition By」キーワード


253

誰かがpartition byキーワードが何をするのかを説明し、実際のキーワードの簡単な例と、なぜそれを使いたいのかを教えてもらえますか?他の誰かが作成したSQLクエリがあり、それが何をするのか理解しようとしています。

次によるパーティションの例:

SELECT empno, deptno, COUNT(*) 
OVER (PARTITION BY deptno) DEPT_COUNT
FROM emp

オンラインで見た例は少々深すぎるようです。


回答:


259

PARTITION BY句は、内の各「グループ」のために使用されるレコードの範囲設定OVER句。

SQLの例でDEPT_COUNTは、すべての従業員レコードについて、その部門内の従業員数を返します。(empテーブルを正規化していないかのように、empテーブル内のすべてのレコードが返されます。)

emp_no  dept_no  DEPT_COUNT
1       10       3
2       10       3
3       10       3 <- three because there are three "dept_no = 10" records
4       20       2
5       20       2 <- two because there are two "dept_no = 20" records

別の列(例:)があった場合state、その州にある部門の数を数えることができます。

これは、結果得るようなものであるGROUP BYSUMAVG(すなわち、一致するレコードを削除)結果セットを集約せずに、など)。

LAST OVERまたはMIN OVER関数を使用して、たとえば部門の最低給与と最高給与を取得し、それを副選択なしでこのレコード給与に対する計算で使用すると、はるかに高速になります。

詳細については、リンクされているAskTomの記事を参照してください。


6
LAST_VALUE-最後の給与を返し、MAXは最高の給与を返します
Maciek Kreft

1
「副選択なし、はるかに遅い」という意味ですか?私は、サブが遅くまたは速くより選択した場合、私は混乱していると思うlast overmin over。私は副選択が遅くなると思いますが、答えの英語の文法はそれを示唆していません。
Jason

このアプローチにより、行が処理される回数が減り、副選択よりも効率的になります。非常に大きなデータセットで最も顕著です。

164

概念は、受け入れられた回答で非常によく説明されていますが、見られる例が多ければ多いほど、よく理解できるようになります。増分例は次のとおりです。

1)ボスは「ブランド別にグループ化された在庫のあるアイテムの数を取得してください」と言います

あなたは言う:「問題ない」

SELECT 
      BRAND
      ,COUNT(ITEM_ID) 
FROM 
      ITEMS
GROUP BY 
      BRAND;

結果:

+--------------+---------------+
|  Brand       |   Count       | 
+--------------+---------------+
| H&M          |     50        |
+--------------+---------------+
| Hugo Boss    |     100       |
+--------------+---------------+
| No brand     |     22        |
+--------------+---------------+

2)上司は、「今、すべてのアイテムのリストと、そのブランドと、それぞれのブランドが持っているアイテムの数を取得してください」と言います。

あなたは試すことができます:

 SELECT 
      ITEM_NR
      ,BRAND
      ,COUNT(ITEM_ID) 
 FROM 
      ITEMS
 GROUP BY 
      BRAND;

しかし、あなたは得る:

ORA-00979: not a GROUP BY expression 

これがOVER (PARTITION BY BRAND)出てくるところです:

 SELECT 
      ITEM_NR
      ,BRAND
      ,COUNT(ITEM_ID) OVER (PARTITION BY BRAND) 
 FROM 
      ITEMS;

Whicとは:

  • COUNT(ITEM_ID) -アイテムの数を取得する
  • OVER -行のセットの上
  • (PARTITION BY BRAND) -同じブランドのもの

そして結果は:

+--------------+---------------+----------+
|  Items       |  Brand        | Count()  |
+--------------+---------------+----------+
|  Item 1      |  Hugo Boss    |   100    | 
+--------------+---------------+----------+
|  Item 2      |  Hugo Boss    |   100    | 
+--------------+---------------+----------+
|  Item 3      |  No brand     |   22     | 
+--------------+---------------+----------+
|  Item 4      |  No brand     |   22     | 
+--------------+---------------+----------+
|  Item 5      |  H&M          |   50     | 
+--------------+---------------+----------+

等...


3
グループごとに1つの結果を取得したい場合は、どうすれば取得できますか?
Viuu -a

OVER PARTITION BYをWHERE句で使用できるかどうか知っていますか?
Kevin Burton

私は、SOについて質問し、具体的に説明し、達成したいことを説明することをお勧めします
Andrejs

@ Viuu-a:おそらく単純なGROUP BYを使用したいと思うでしょう。
jackthehipster

この例が大好きです...理解しやすい
ジョニーウー

27

これは、アナリティクスと呼ばれるSQL拡張機能です。selectステートメントの「over」は、関数が分析関数であり、関数ごとのグループではないことをオラクルに伝えます。分析を使用する利点は、副選択またはさらに悪いPL / SQLでデータをループする代わりに、データの1回のパススルーで合計、カウントなどを収集できることです。

最初は混乱するように見えますが、これはすぐに第二の性質になります。誰もトム・カイトより良い説明はしません。上記のリンクは素晴らしいです。

もちろん、ドキュメントを読むことは必須です。


9
EMPNO     DEPTNO DEPT_COUNT

 7839         10          4
 5555         10          4
 7934         10          4
 7782         10          4 --- 4 records in table for dept 10
 7902         20          4
 7566         20          4
 7876         20          4
 7369         20          4 --- 4 records in table for dept 20
 7900         30          6
 7844         30          6
 7654         30          6
 7521         30          6
 7499         30          6
 7698         30          6 --- 6 records in table for dept 30

ここでは、それぞれのdeptnoの数を取得しています。deptno 10については、テーブルempに4つのレコードがあり、deptno 20および30についても同様の結果が得られます。


12
PARTITION byがどのように機能するかという質問に対する説明はありません。出力例だけでは、質問に完全に答えることはできません。
Siraj Samsudeen 2013

2

over partitionキーワードは、client_idの作成によってデータをパーティション化しているように、各クライアントIDのサブセットを作成します。

select client_id, operation_date,
       row_number() count(*) over (partition by client_id order by client_id ) as operationctrbyclient
from client_operations e
order by e.client_id;

このクエリは、client_idによって実行された操作の数を返します


0

この例は、パーティショニングがどのように機能し、group byがどのように機能するかについて、わずかなニュアンスを示唆していると思います。私の例がたまたまコンパイルバグである場合、私の例はOracle 12からのものです。

私は試した :

SELECT t.data_key
,      SUM ( CASE when t.state = 'A' THEN 1 ELSE 0 END) 
OVER   (PARTITION BY t.data_key) count_a_rows
,      SUM ( CASE when t.state = 'B' THEN 1 ELSE 0 END) 
OVER   (PARTITION BY t.data_key) count_b_rows
,      SUM ( CASE when t.state = 'C' THEN 1 ELSE 0 END) 
OVER   (PARTITION BY t.data_key) count_c_rows
,      COUNT (1) total_rows
from mytable t
group by t.data_key  ---- This does not compile as the compiler feels that t.state isn't in the group by and doesn't recognize the aggregation I'm looking for

ただし、これは期待どおりに機能します。

SELECT distinct t.data_key
,      SUM ( CASE when t.state = 'A' THEN 1 ELSE 0 END) 
OVER   (PARTITION BY t.data_key) count_a_rows
,      SUM ( CASE when t.state = 'B' THEN 1 ELSE 0 END) 
OVER   (PARTITION BY t.data_key) count_b_rows
,      SUM ( CASE when t.state = 'C' THEN 1 ELSE 0 END) 
OVER   (PARTITION BY t.data_key) count_c_rows
,      COUNT (1) total_rows
from mytable t;

外部キー「data_key」に基づいて、各状態の要素数を生成します。したがって、data_key = 'APPLE'に状態 'A'の3行、状態 'B'の2行、状態 'C'の行がある場合、 'APPLE'の対応する行は 'APPLE'、3、2になります。 、1、6。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.