Ответ 1
PARTITION BY
Сегрегированные наборы, это позволяет вам работать (ROW_NUMBER(), COUNT(), SUM() и т.д.) для соответствующего набора независимо.
В вашем запросе связанный набор состоит из строк с похожими cdt.country_code, cdt.account, cdt.currency. Когда вы разделяете эти столбцы и применяете к ним ROW_NUMBER. Эти другие столбцы в этой комбинации/наборе получат последовательный номер из ROW_NUMBER
Но этот запрос забавный, если ваш раздел по каким-то уникальным данным и вы поместите на него строку row_number, он просто произведет такое же число. Как и вы, ORDER BY на разделе, который гарантированно будет уникальным. Например, подумайте о GUID как уникальной комбинации cdt.country_code, cdt.account, cdt.currency
newid()
создает GUID, так что вы ожидаете от этого выражения?
select
hi,ho,
row_number() over(partition by newid() order by hi,ho)
from tbl;
... Правильно, все секционированные (ни один не был разбит на разделы, каждая строка разделена на свою строку). Строки row_numbers все установлены в 1
В принципе, вы должны разбить на неповторимые столбцы. ORDER BY на OVER требовал, чтобы PARTITION BY имел уникальную комбинацию, иначе все row_numbers станут 1
Например, это ваши данные:
create table tbl(hi varchar, ho varchar);
insert into tbl values
('A','X'),
('A','Y'),
('A','Z'),
('B','W'),
('B','W'),
('C','L'),
('C','L');
Тогда это аналогично вашему запросу:
select
hi,ho,
row_number() over(partition by hi,ho order by hi,ho)
from tbl;
Каков будет результат этого?
HI HO COLUMN_2
A X 1
A Y 1
A Z 1
B W 1
B W 2
C L 1
C L 2
Вы видите комбинацию HI HO? Первые три строки имеют уникальную комбинацию, поэтому они установлены в 1, строки B имеют одинаковые W, следовательно, разные ROW_NUMBERS, аналогично строкам HI C.
Теперь, зачем нужен ORDER BY
? Если предыдущий разработчик просто хочет поставить row_number на подобные данные (например, HI B, все данные B-W, B-W), он может просто сделать это:
select
hi,ho,
row_number() over(partition by hi,ho)
from tbl;
Но, увы, Oracle (и Sql Server тоже) не разрешает раздел без ORDER BY
; тогда как в Postgresql ORDER BY
на PARTITION необязательно: http://www.sqlfiddle.com/#!1/27821/1
select
hi,ho,
row_number() over(partition by hi,ho)
from tbl;
Ваш ORDER BY
в вашем разделе выглядит немного избыточным, а не из-за предыдущей ошибки разработчика, некоторые базы данных просто не позволяют PARTITION
без ORDER BY
, он может не найти хороший столбец-кандидат для сортировки на. Если оба столбца PARTITION BY и столбцы ORDER BY одинаковы, просто удалите ORDER BY, но, поскольку некоторая база данных не позволяет это, вы можете просто сделать это:
SELECT cdt.*,
ROW_NUMBER ()
OVER (PARTITION BY cdt.country_code, cdt.account, cdt.currency
ORDER BY newid())
seq_no
FROM CUSTOMER_DETAILS cdt
Вы не можете найти хороший столбец для сортировки похожих данных? Вы также можете сортировать случайным образом, в любом случае для секционированных данных одинаковые значения. Например, вы можете использовать GUID (вы используете newid()
для SQL Server). Таким образом, тот же результат, производимый предыдущим разработчиком, к сожалению, некоторая база данных не позволяет PARTITION
без ORDER BY
Хотя на самом деле это ускользает от меня, и я не могу найти вескую причину, чтобы поместить число в те же комбинации (B-W, B-W в примере выше). Это создает впечатление, что база данных имеет избыточные данные. Как-то напомнил мне об этом: Как получить одну уникальную запись из того же списка записей из таблицы? Нет уникального ограничения в таблице
Это действительно выглядит тайным, видя PARTITION BY с той же комбинацией столбцов с ORDER BY, не может легко сделать вывод о намерении кода.
Live test: http://www.sqlfiddle.com/#!3/27821/6
Но, как заметил и dbaseman, бесполезно разбивать и упорядочивать одни и те же столбцы.
У вас есть набор таких данных:
create table tbl(hi varchar, ho varchar);
insert into tbl values
('A','X'),
('A','X'),
('A','X'),
('B','Y'),
('B','Y'),
('C','Z'),
('C','Z');
Затем вы разделяете привет, хо; и тогда вы ЗАКАЗЫВАЕТ привет, хо. Нет смысла нумерации похожих данных:-) http://www.sqlfiddle.com/#!3/29ab8/3
select
hi,ho,
row_number() over(partition by hi,ho order by hi,ho) as nr
from tbl;
Вывод:
HI HO ROW_QUERY_A
A X 1
A X 2
A X 3
B Y 1
B Y 2
C Z 1
C Z 2
См? Зачем нужно указывать номера строк в одной комбинации? Что вы проанализируете на тройной A, X, на двойном B, Y, на двойном C, Z?: -)
Вам просто нужно использовать PARTITION для неисторического столбца, а затем сортировать по уникальной колонке уникальных столбцов. Пример сделает его более понятным:
create table tbl(hi varchar, ho varchar);
insert into tbl values
('A','D'),
('A','E'),
('A','F'),
('B','F'),
('B','E'),
('C','E'),
('C','D');
select
hi,ho,
row_number() over(partition by hi order by ho) as nr
from tbl;
PARTITION BY hi
работает с не уникальным столбцом, затем в каждом секционированном столбце вы заказываете его уникальный столбец (ho), ORDER BY ho
Вывод:
HI HO NR
A D 1
A E 2
A F 3
B E 1
B F 2
C D 1
C E 2
Этот набор данных имеет больше смысла
Live test: http://www.sqlfiddle.com/#!3/d0b44/1
И это похоже на ваш запрос с одинаковыми столбцами как на PARTITION BY, так и на ORDER BY:
select
hi,ho,
row_number() over(partition by hi,ho order by hi,ho) as nr
from tbl;
И это выход:
HI HO NR
A D 1
A E 1
A F 1
B E 1
B F 1
C D 1
C E 1
См? нет смысла?
Live test: http://www.sqlfiddle.com/#!3/d0b44/3
Наконец, это может быть правильный запрос:
SELECT cdt.*,
ROW_NUMBER ()
OVER (PARTITION BY cdt.country_code, cdt.account -- removed: cdt.currency
ORDER BY
-- removed: cdt.country_code, cdt.account,
cdt.currency) -- keep
seq_no
FROM CUSTOMER_DETAILS cdt