PARTITION BY
conjuntos separados, esto le permite poder trabajar (ROW_NUMBER(), COUNT(), SUM(), etc.) en conjuntos relacionados de forma independiente.
En su consulta, el conjunto relacionado consta de filas con cdt.country_code, cdt.account, cdt.currency similares. Cuando realiza la partición en esas columnas y aplica ROW_NUMBER en ellas. Esas otras columnas en esa combinación/conjunto recibirán un número secuencial de ROW_NUMBER
Pero esa consulta es divertida, si su partición por algunos datos únicos y le pone un número de fila, simplemente producirá el mismo número. Es como si hicieras un ORDEN POR en una partición que está garantizada como única. Ejemplo, piense en GUID como una combinación única de cdt.country_code, cdt.account, cdt.currency
newid()
produce GUID, entonces, ¿qué esperará de esta expresión?
select
hi,ho,
row_number() over(partition by newid() order by hi,ho)
from tbl;
... Correcto, todas las filas particionadas (ninguna fue particionada, cada fila está dividida en su propia fila) los números de fila de las filas están todos establecidos en 1
Básicamente, debe particionar en columnas no únicas. ORDER BY on OVER necesitaba que PARTITION BY tuviera una combinación no única; de lo contrario, todos los números de fila se convertirán en 1
Un ejemplo, estos son tus datos:
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');
Entonces esto es análogo a su consulta:
select
hi,ho,
row_number() over(partition by hi,ho order by hi,ho)
from tbl;
¿Cuál será el resultado de eso?
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
¿Ves la combinación de HI HO? Las primeras tres filas tienen una combinación única, por lo tanto, se establecen en 1, las filas B tienen la misma W, por lo tanto, ROW_NUMBERS diferentes, al igual que las filas HI C.
Ahora, ¿por qué ORDER BY
se necesita ahi? Si el desarrollador anterior simplemente quiere poner un número de fila en datos similares (por ejemplo, HI B, todos los datos son B-W, B-W), puede hacer esto:
select
hi,ho,
row_number() over(partition by hi,ho)
from tbl;
Pero, por desgracia, Oracle (y Sql Server también) no permite la partición sin ORDER BY
; mientras que en Postgresql, ORDER BY
en PARTICIÓN es opcional:http://www.sqlfiddle.com/#!1/27821/1
select
hi,ho,
row_number() over(partition by hi,ho)
from tbl;
Tu ORDER BY
en su partición parece un poco redundante, no por culpa del desarrollador anterior, algunas bases de datos simplemente no permiten PARTITION
sin ORDER BY
, es posible que no pueda encontrar una buena columna candidata para ordenar. Si las columnas PARTICIÓN POR y ORDEN POR son iguales, simplemente elimine ORDEN POR, pero como algunas bases de datos no lo permiten, puede hacer esto:
SELECT cdt.*,
ROW_NUMBER ()
OVER (PARTITION BY cdt.country_code, cdt.account, cdt.currency
ORDER BY newid())
seq_no
FROM CUSTOMER_DETAILS cdt
¿No puede encontrar una buena columna para ordenar datos similares? También puede ordenar al azar, los datos particionados tienen los mismos valores de todas formas. Puede usar GUID por ejemplo (usa newid()
para el servidor SQL). Entonces, tiene el mismo resultado realizado por el desarrollador anterior, es desafortunado que alguna base de datos no permita PARTITION
sin ORDER BY
Aunque en realidad, se me escapa y no puedo encontrar una buena razón para poner un número en las mismas combinaciones (B-W, B-W en el ejemplo anterior). Da la impresión de que la base de datos tiene datos redundantes. De alguna manera me recordó esto:¿Cómo obtener un registro único de la misma lista de registros de la tabla? Sin restricción única en la tabla
Realmente parece extraño ver una PARTICIÓN POR con la misma combinación de columnas con ORDEN POR, no se puede inferir fácilmente la intención del código.
Prueba en vivo:http://www.sqlfiddle.com/#!3/27821/6
Pero como también ha notado dbaseman, es inútil particionar y ordenar en las mismas columnas.
Tienes un conjunto de datos como este:
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');
Entonces usted PARTICIONA POR hola, ho; y luego ORDENA POR hi,ho. No tiene sentido numerar datos similares :-) 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;
Salida:
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
¿Ver? ¿Por qué es necesario poner números de fila en la misma combinación? ¿Qué analizarás sobre triple A,X, sobre doble B,Y, sobre doble C,Z? :-)
Solo necesita usar PARTICIÓN en una columna no única, luego ordenar en columna(s) no única(s) único -ing columna. El ejemplo lo hará más claro:
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
opera en una columna no única, luego en cada columna particionada, ordena en su columna única (ho), ORDER BY ho
Salida:
HI HO NR
A D 1
A E 2
A F 3
B E 1
B F 2
C D 1
C E 2
Ese conjunto de datos tiene más sentido
Prueba en vivo:http://www.sqlfiddle.com/#!3/d0b44/1
Y esto es similar a su consulta con las mismas columnas en PARTICIÓN POR y ORDEN POR:
select
hi,ho,
row_number() over(partition by hi,ho order by hi,ho) as nr
from tbl;
Y esta es la salida:
HI HO NR
A D 1
A E 1
A F 1
B E 1
B F 1
C D 1
C E 1
¿Ver? no tiene sentido?
Prueba en vivo:http://www.sqlfiddle.com/#!3/d0b44/3
Finalmente, esta podría ser la consulta correcta:
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