Ключове слово "Розділ за" Oracle


253

Чи може хтось, будь ласка, пояснити, що partition byробить ключове слово, і навести простий приклад його в дії, а також чому б його хотіли використовувати? У мене є запит SQL, написаний кимось іншим, і я намагаюся з'ясувати, що це робить.

Приклад розділу за:

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

Приклади, які я бачив в Інтернеті, здаються занадто поглибленими.


Інша важлива посилання: postgresql.org/docs/9.1/static/tutorial-window.html
Shashank Вівек

Відповіді:


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 BY( SUM, AVGі т.д.) без об'єднання набору результатів (тобто видалення співпадаючих записів).

Це корисно, коли ви використовуєте LAST OVERабо MIN OVERфункції, щоб отримати, наприклад, найнижчу та найвищу зарплату у відділі, а потім використовувати це у розрахунку проти цього запису зарплати без підбору вибору, що набагато швидше.

Прочитайте пов'язану статтю AskTom для отримання додаткової інформації.


6
LAST_VALUE - повертає останню зарплату, MAX повертає найвищу зарплату
Maciek Kreft

1
Ви маєте на увазі "без суб-вибору, який набагато повільніше"? Я думаю, що я плутаюсь, якщо вибір sub є повільнішим або швидшим ніж last overта min over. Я думаю, що підбір субмедіату буде повільніше, але граматика англійської мови у відповіді цього не підказує.
Джейсон

Такий підхід зменшує кількість обробок рядків, що робить його більш ефективним, ніж підбір. Найбільш помітний у дуже великих наборах даних.
Хлопець

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;

Що означає:

  • 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
Якщо я хочу отримати один результат для кожної групи .. Як я його отримаю?
Viuu -a

Чи знаєте ви, чи можна використовувати OVER PARTITION BY у пункті WHERE?
Кевін Бертон

Я пропоную вам задати запитання щодо ТА, надати конкретику та пояснити, чого ви хочете досягти
Андрейс

@ Viuu-a: Тоді ви, мабуть, захочете скористатися простою групою BY.
jackthehipster

люблю цей приклад ... легко зрозуміти
Джонні Ву

27

Це розширення SQL, яке називається аналітикою. Оператор "over" у select select говорить оракулу, що функція є аналітичною функцією, а не груповою функцією. Перевагою використання аналітики є те, що ви можете збирати суми, рахунки та багато іншого лише за один прохід даних замість того, щоб переглядати дані з підбором або гірше PL / SQL.

Спочатку це виглядає заплутано, але це буде швидко по-другому. Ніхто не пояснює це краще, ніж Том Кіт. Тож посилання вище чудове.

Звичайно, читання документації є обов'язковим.


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 10, то у таблиці 4 записів є аналогічні результати для 20 і 30 також.


12
Немає роз'яснення на питання про те, як діє ПАРТІЯ. Тільки приклад прикладу не відповідає повністю на питання.
Siraj Samsudeen

2

ключове слово over partition - це так, ніби ми розділяємо дані, створюючи client_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

Я думаю, цей приклад пропонує невеликий нюанс щодо того, як працює розділення та як групується за роботами. Мій приклад - з 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' було 3 рядки зі станом 'A', 2 рядки зі станом 'B', рядок зі станом 'C', відповідний рядок для 'APPLE' буде 'APPLE', 3, 2 , 1, 6.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.