Eu preciso de uma função agregada que o MySQL não fornece.
Eu gostaria que fosse no estilo SQL do MySQL (ou seja, não em C).
Como eu faço isso? O que estou travando é criar uma função agregada - os documentos não parecem mencionar como isso é feito.
Exemplos de uso desejado de uma product
função:
mysql> select product(col) as a from `table`;
+------+
| a |
+------+
| 144 |
+------+
1 row in set (0.00 sec)
mysql> select col, product(col) as a from `table` group by col;
+-----+------+
| col | a |
+-----+------+
| 6 | 36 |
| 4 | 4 |
+-----+------+
2 rows in set (0.01 sec)
Não sei se há como definir uma nova função agregada, não sem mexer no código-fonte do MySQL.
Mas se seus números são todos positivos, você pode derivar da identidade aritmética:
que você pode usar
EXP(SUM(LOG(x)))
para calcularPRODUCT(x)
. Teste no SQL-Fiddle :Quando os dados podem ter 0s, fica um pouco mais complicado:
Testado no SQL-Fiddle
Para outros SGBDs, que não possuam a autoconversão do MySQL de valores booleanos para inteiros, o
deve ser substituído por:
Especificamente para o Oracle, serão necessárias mais algumas alterações, sem alterar a lógica da resposta, apenas porque o Oracle não segue rígido padrão ANSI em algumas áreas. Testado no SQL-Fiddle-2
De acordo com a documentação http://dev.mysql.com/doc/refman/5.5/en/adding-udf.html só é possível escrever funções agregadas em C. Desculpe!
No interesse de aprender a pescar, compilei e instalei com sucesso um "Hello, World!" UDF (função definida pelo usuário) para MySQL encontrada aqui . O arquivo hello_world.so (depois de cumprido
gcc -shared -o hello_world.so -I /usr/include/mysql hello_world.c
) deve ser armazenado em /usr/lib/mysql/plugins/ com 755 permissões em sistemas Ubuntu linux. [O "-I /usr/include/mysql" é o caminho para os arquivos de cabeçalho mysql; Descobri que meu código não compilaria sem esse parâmetro, mas YMMV.]O programa não faz nada além de imprimir a string "Hello, World!" para cada registro no conjunto de dados resultante de uma consulta, mas isso é tudo o que deve fazer. Vou tentar escrever uma função de agregação PEQUENA nos próximos dias. Há um exemplo de função agregada que calcula o custo médio de um grupo de registros de preço e quantidade; a função SMALL não deve ser tão diferente dessa função no final.
Espero que isto ajude.
Tecnicamente, não é uma função agregada definida pelo usuário e não é ideal, mas funciona e não precisa criar um UDF: use
GROUP_CONCAT()
em sua consulta, o que tornará sua consulta agregada e consolidará todos os valores em uma string separada por vírgula e em seguida, escreva uma função SQL que processe essa string.Exemplo (função baseada nesta resposta)::
Tábua:
Consulta:
Traduzirá para:
Qual para esta função personalizada específica retornará
my two cents