Kata Kunci "Partition By" Oracle

253

Dapatkah seseorang tolong jelaskan apa yang dilakukan partition bykata kunci dan berikan contoh sederhana dalam tindakan, serta mengapa orang ingin menggunakannya? Saya memiliki query SQL yang ditulis oleh orang lain dan saya mencoba mencari tahu apa fungsinya.

Contoh partisi dengan:

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

Contoh yang saya lihat online tampak agak terlalu mendalam.

Alex Beardsley
sumber
Tautan lain yang relevan: postgresql.org/docs/9.1/static/tutorial-window.html
Shashank Vivek

Jawaban:

259

The PARTITION BYklausul menetapkan berbagai catatan yang akan digunakan untuk setiap "GROUP" dalam OVERklausa.

Dalam contoh Anda SQL, DEPT_COUNTakan mengembalikan jumlah karyawan dalam departemen itu untuk setiap catatan karyawan. (Seolah-olah Anda men-nomalisasi emptabel; Anda masih mengembalikan setiap record di emptabel.)

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

Jika ada kolom lain (misalnya, state) maka Anda dapat menghitung berapa banyak departemen di Negara tersebut.

Hal ini seperti mendapatkan hasil GROUP BY( SUM, AVG, dll) tanpa menggabungkan hasil set (yaitu menghapus catatan yang cocok).

Ini berguna ketika Anda menggunakan fungsi LAST OVERatau MIN OVERuntuk mendapatkan, misalnya, gaji terendah dan tertinggi di departemen dan kemudian menggunakannya dalam perhitungan terhadap catatan ini gaji tanpa sub pilih, yang jauh lebih cepat.

Baca artikel AskTom yang tertaut untuk perincian lebih lanjut.

Orang
sumber
6
LAST_VALUE - mengembalikan gaji terakhir, MAX mengembalikan gaji tertinggi
Maciek Kreft
1
Apakah maksud Anda "tanpa sub pilih, yang jauh lebih lambat"? Saya kira saya bingung jika sub pilih lebih lambat atau lebih cepat dari last overdan min over. Saya akan membayangkan sub pilih akan lebih lambat, tetapi tata bahasa Inggris dalam jawabannya tidak menyarankan itu.
Jason
Pendekatan ini mengurangi berapa kali baris diproses, membuatnya lebih efisien daripada subselect. Paling terlihat dalam kumpulan data yang sangat besar.
Guy
164

Konsep ini dijelaskan dengan sangat baik oleh jawaban yang diterima, tetapi saya menemukan bahwa semakin banyak contoh yang dilihat, semakin baik tenggelam. Berikut adalah contoh tambahan:

1) Boss berkata "dapatkan saya jumlah barang yang ada dalam stok yang dikelompokkan berdasarkan merek"

Anda mengatakan : "tidak masalah"

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

Hasil:

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

2) Bos berkata "Sekarang ambilkan saya daftar semua barang, dengan merek mereka DAN jumlah barang yang dimiliki masing-masing merek"

Anda dapat mencoba:

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

Tapi Anda mendapatkan:

ORA-00979: not a GROUP BY expression 

Di sinilah OVER (PARTITION BY BRAND)masuk:

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

Yang artinya:

  • COUNT(ITEM_ID) - dapatkan jumlah item
  • OVER - Lebih dari set baris
  • (PARTITION BY BRAND) - yang memiliki merek yang sama

Dan hasilnya adalah:

+--------------+---------------+----------+
|  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     | 
+--------------+---------------+----------+

dll ...

Andrejs
sumber
3
Jika saya ingin mendapatkan satu hasil untuk setiap grup .. Bagaimana cara saya mendapatkannya?
Viuu -a
Apakah Anda tahu jika OVER PARTITION BY dapat digunakan dalam klausa WHERE?
Kevin Burton
Saya sarankan Anda mengajukan pertanyaan pada SO, memberikan spesifik dan menjelaskan apa yang ingin Anda capai
Andrejs
@ Viuu-a: Maka Anda mungkin ingin menggunakan GROUP BY sederhana.
jackthehipster
suka contoh ini ... mudah dimengerti
Johnny Wu
27

Ini adalah ekstensi SQL yang disebut analytics. "Lebih" dalam pernyataan pilih memberi tahu oracle bahwa fungsi tersebut adalah fungsi analitis, bukan fungsi kelompok. Keuntungan menggunakan analitik adalah Anda dapat mengumpulkan jumlah, jumlah, dan banyak lagi hanya dengan satu kali melewati data alih-alih mengulang-ulang data dengan sub seleksi atau lebih buruk, PL / SQL.

Itu memang terlihat membingungkan pada awalnya tetapi ini akan menjadi sifat kedua dengan cepat. Tidak ada yang menjelaskan lebih baik daripada Tom Kyte. Jadi tautan di atas sangat bagus.

Tentu saja, membaca dokumentasi adalah suatu keharusan.

pengguna60890
sumber
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

Di sini kita mendapatkan hitungan untuk masing-masing deptno. Adapun deptno 10 kami memiliki 4 catatan dalam tabel emp hasil yang sama untuk deptno 20 dan 30 juga.


sumber
12
Tidak ada penjelasan untuk pertanyaan bagaimana PARTISI bekerja. Contoh output saja tidak sepenuhnya menjawab pertanyaan.
Siraj Samsudeen
2

kata kunci over partisi adalah seolah-olah kita mempartisi data dengan client_id membuat subset dari setiap id klien

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;

kueri ini akan mengembalikan jumlah operasi yang dilakukan oleh client_id

masalah
sumber
0

Saya pikir, contoh ini menunjukkan nuansa kecil tentang cara kerja partisi dan cara kerja kelompok. Contoh saya adalah dari Oracle 12, jika contoh saya adalah bug kompilasi.

Saya mencoba :

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

Namun ini berfungsi seperti yang diharapkan:

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;

Memproduksi jumlah elemen di setiap negara berdasarkan kunci eksternal "data_key". Jadi, jika, data_key = 'APPLE' memiliki 3 baris dengan status 'A', 2 baris dengan status 'B', satu baris dengan status 'C', baris yang sesuai untuk 'APPLE' adalah 'APPLE', 3, 2 , 1, 6.

georgejo
sumber