PostgreSQL Window Functions
Como o David Feeter me prometeu na pg-con ano passado o pessoal do postgreSQL implementou as famosas window functions. As “windows” são os dados “sobre” os quais você irá trabalhar. Daí o nome window e daí também o noe da mais famosa delas over.
Um exemplo simples tirado direto da documentação oficial do 8.4 pode nos ajudar a entender o que isso significa na pratica.
SELECT depname, empno, salary, avg(salary) OVER (PARTITION BY depname) FROM empsalary;
depname | empno | salary | avg
———–+——-+——–+———————–
develop | 11| 5200 | 5020.0000000000000000
develop | 7 | 4200 | 5020.0000000000000000
develop | 9 | 4500 | 5020.0000000000000000
develop | 8 | 6000 | 5020.0000000000000000
develop | 10| 5200 | 5020.0000000000000000
personnel | 5 | 3500 | 3700.0000000000000000
personnel | 2 | 3900 | 3700.0000000000000000
sales | 3 | 4800 | 4866.6666666666666667
sales | 1 | 5000 | 4866.6666666666666667
sales | 4 | 4800 | 4866.6666666666666667
(10 rows)
O que vemos aí é que foi pedido para calcular a média dos salarios “em cima do departamento”. Algo parecido com um agrupamento pelo departamento, só que sem agrupar na verdade. Com o uso da função partition by o que nós fizemos foi o seguinte, pedimos que o resultado fosse particionado ao invéz de agrupado.
A diferença entre particionar e agrupar é que no particionamento nós mostramos o resultado de nossa função de agregação (avg) para cada uma das linhas que nos fizeram chegar a esse resultado. No caso de um agrupamento nós traríamos apenas a média por desses salários por setor.
Em muitos casos pode ser útil ver não só a media dos salários por setor mas ainda cada linha que nos fez chegar a essa média.
Outro caso o qual me deparei varias vezes em uma migração foi o que a funcao escrita em Pl/SQL precisava apenas mostrar um numero de linha que deveria reinicar a cada mudança de um determinado campo.
Ex:
row_number() | funcionario | setor
——————+—————+————————-
1 | coutinho | db
2 | magno | db
3 | marcos | db
1 | joao | desenvolvimento
2 | chico | desenvolvimento
3 | jose | desenvolvimento
4 | paulo | desenvolvimento
(7 rows)
Isso é o resultado de um:
select row_numer() over(partition by setor), funcionario, setor from vw_funcionario_por_setor
Isso que nos dizer que queremos o numero de cada linha dentro da janela delimitada pelo setor.
O resultado visual é uma sequencia numérica que é reiniciada quando muda de setor.
Essas funções me fizeram muita falta, estou ancioso pelo 8.4.

Todos nós estamos ansiosos coutinho… “:)
Comment by Guedes — March 7, 2009 @ 6:54 pm
row_number() ?
Você implementou essa rotina ou é outra novidade da versão nova ?
Eu conheço ROWNUM no oracle, mas no postgres sempre precisei improvisar com sequencias.
Comment by Hamilton R. Amorim — June 23, 2009 @ 6:46 pm