Oracle “Bölümleme” Anahtar Kelimesi


254

Birisi lütfen partition byanahtar kelimenin ne yaptığını açıklayabilir ve basit bir eylem örneğini ve neden onu kullanmak isteyeceğini açıklayabilir mi? Başka biri tarafından yazılmış bir SQL sorgusu var ve ne yaptığını anlamaya çalışıyorum.

Bölümleme örneği:

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

İnternette gördüğüm örnekler biraz derinlemesine görünüyor.


Yanıtlar:


260

PARTITION BYHükmü içindeki her bir "GROUP" için kullanılacak kayıt aralığını belirler OVERmaddesi.

Örnek SQL'inizde, DEPT_COUNTher çalışan kaydı için o departmandaki çalışan sayısını döndürür. (Sanki empmasayı dekalifiye ediyormuşsunuzdur ; yine de emptablodaki her kaydı döndürürsünüz .)

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

Başka bir sütun (ör. state) Varsa, o Eyalette kaç bölüm olduğunu sayabilirsiniz.

Sonuç kümesini toplamadan (yani eşleşen kayıtları kaldırma) bir GROUP BY( SUM, AVGvb.) Sonuçlarını almak gibidir .

Örneğin, departmanda en düşük ve en yüksek maaşı almak için LAST OVERveya MIN OVERişlevlerini kullandığınızda ve daha sonra, bu daha düşük bir alt seçim olmadan maaş kayıtlarına karşı bir hesaplamada kullandığınızda , bu çok daha hızlıdır.

Daha fazla bilgi için bağlantılı AskTom makalesini okuyun .


6
LAST_VALUE - son maaş, MAX en yüksek maaş döndürür
Maciek Kreft

1
Şunu mu demek istediniz: "bir alt seçim olmadan, çok daha yavaş"? Ben alt yavaş veya daha hızlı olduğunu seçerseniz ben karıştı galiba last overve min over. Bir alt seçim daha yavaş olacağını düşünürdüm, ama cevap İngilizce dilbilgisi bunu önermiyor.
Jason

Bu yaklaşım, satırların işlenme sayısını azaltır ve bir alt seçime göre daha verimli hale getirir. En çok çok büyük veri setlerinde fark edilir.
Guy

164

Kavram, kabul edilen cevapla çok iyi açıklanmıştır, ancak bir insan ne kadar çok görürse, o kadar iyi battığını görüyorum. İşte artımlı bir örnek:

1) Patron diyor ki "stoklarımızda bulunan marka sayısını bana göre markalayın"

"Sorun değil" diyorsunuz

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

Sonuç:

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

2) Patron, "Şimdi bana markalarının VE ilgili markanın sahip olduğu parça sayısıyla tüm öğelerin bir listesini alın" diyor

Deneyebilirsiniz:

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

Ama şunu elde edersiniz:

ORA-00979: not a GROUP BY expression 

İşte bu noktada OVER (PARTITION BY BRAND)devreye giriyor:

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

Hangi anlama gelir?

  • COUNT(ITEM_ID) - öğe sayısını al
  • OVER - Satır kümesi üzerinde
  • (PARTITION BY BRAND) - aynı markaya sahip

Ve sonuç:

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

vb...


3
Her grup için bir sonuç almak istersem .. Nasıl elde edeceğim?
Viuu -a

OVER PARTITION BY bir WHERE yan tümcesinde kullanılabilir mi, biliyor musunuz?
Kevin Burton

Ben SO hakkında bir soru sormak, özellikler vermek ve ne elde etmek istediğinizi açıklamak öneririm
Andrejs

@ Viuu-a: O zaman muhtemelen basit bir GROUP BY kullanmak isteyeceksiniz.
jackthehipster

Bu örneği seviyorum ... kolay anlaşılır
Johnny Wu

27

Analitik adı verilen SQL uzantısıdır. Select deyimindeki "over", işleve, gruba göre değil, analitik bir işlev olduğunu bildirir. Analitiği kullanmanın avantajı, alt seçimler veya daha kötüsü PL / SQL ile veriler arasında dolaşmak yerine, verilerin tek bir geçişiyle toplamları, sayıları ve çok daha fazlasını toplayabilmenizdir.

İlk başta kafa karıştırıcı görünüyor, ancak bu hızla ikinci doğa olacak. Kimse bunu Tom Kyte'den daha iyi açıklamaz. Yani yukarıdaki bağlantı harika.

Tabii ki, belgeleri okumak bir zorunluluktur.


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

Burada ilgili deptno için sayı alıyoruz. Deptno 10'a gelince, tablo 4 de deptno 20 ve 30 için benzer sonuçlara sahibiz.


12
BÖLME tarafından nasıl çalıştığı sorusuna herhangi bir açıklama yapılmamıştır. Sadece örnek çıktı tek başına soruyu tam olarak cevaplamaz.
Siraj Samsudeen

2

over partition anahtar sözcüğü, client_id oluşturma yoluyla verileri her bir müşteri kimliğinin bir alt kümesi olarak bölümliyormuşuz gibi

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;

bu sorgu client_id tarafından yapılan işlem sayısını döndürür


0

Bence bu örnek, bölümlemenin nasıl çalıştığı ve gruplara göre nasıl çalıştığı hakkında küçük bir nüans önermektedir. Örneğim derleyici bir hata olduğunda, örneğim Oracle 12'den.

Denedim :

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

Ancak bu beklendiği gibi çalışır:

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" harici anahtarını temel alarak her bir durumdaki eleman sayısını üretmek. Dolayısıyla, data_key = 'APPLE', 'A' durumuyla 3 satır, 'B' durumuyla 2 satır, 'C' durumuyla bir satır olsaydı, 'APPLE' için karşılık gelen satır 'APPLE', 3, 2 olur , 1, 6.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.