Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Operador de agregação de multiplicação em SQL


Por MUL você quer dizer multiplicação progressiva de valores?

Mesmo com 100 linhas de algum tamanho pequeno (digamos 10s), seu MUL(coluna) vai estourar qualquer tipo de dados! Com uma probabilidade tão alta de uso incorreto/ab-use e escopo muito limitado para uso, não precisa ser um padrão SQL. Como outros mostraram, existem maneiras matemáticas de resolver isso, assim como existem muitas maneiras de fazer cálculos complicados em SQL apenas usando métodos padrão (e de uso comum).

Dados de amostra:
Column
1
2
4
8

COUNT : 4 items (1 for each non-null)
SUM   : 1 + 2 + 4 + 8 = 15
AVG   : 3.75 (SUM/COUNT)
MUL   : 1 x 2 x 4 x 8 ? ( =64 )

Para completar, as principais implementações Oracle, MSSQL, MySQL *
Oracle : EXP(SUM(LN(column)))   or  POWER(N,SUM(LOG(column, N)))
MSSQL  : EXP(SUM(LOG(column)))  or  POWER(N,SUM(LOG(column)/LOG(N)))
MySQL  : EXP(SUM(LOG(column)))  or  POW(N,SUM(LOG(N,column)))
  • Cuidado ao usar EXP/LOG no SQL Server, observe o tipo de retorno http://msdn.microsoft.com/en-us/library/ms187592.aspx
  • A forma POWER permite números maiores (usando bases maiores que o número de Euler), e nos casos em que o resultado fica muito grande para retornar usando POWER, você pode retornar apenas o valor logarítmico e calcular o número real fora do Consulta SQL


* LOG(0) e LOG(-ve) são indefinidos. O abaixo mostra apenas como lidar com isso no SQL Server. Equivalentes podem ser encontrados para os outros tipos de SQL, usando o mesmo conceito

create table MUL(data int)
insert MUL select 1 yourColumn union all
           select 2 union all
           select 4 union all
           select 8 union all
           select -2 union all
           select 0

select CASE WHEN MIN(abs(data)) = 0 then 0 ELSE
       EXP(SUM(Log(abs(nullif(data,0))))) -- the base mathematics
     * round(0.5-count(nullif(sign(sign(data)+0.5),1))%2,0) -- pairs up negatives
       END
from MUL

Ingredientes:
  • pegando o abs() dos dados, se o mínimo for 0, multiplicando por qualquer outra coisa que for inútil, o resultado será 0
  • Quando os dados são 0, NULLIF os converte em nulos. O abs(), log() ambos retornam null, fazendo com que seja excluído de sum()
  • Se os dados não forem 0, abs nos permite multiplicar um número negativo usando o método LOG - acompanharemos a negatividade em outro lugar
  • Desenvolvendo o sinal final
    • sign(data) retorna 1 for >0 , 0 for 0 e -1 for <0 .
    • Adicionamos mais 0,5 e pegamos o sinal() novamente, então agora classificamos 0 e 1 como 1 e apenas -1 como -1.
    • novamente use NULLIF para remover de COUNT() os 1's, pois só precisamos contar os negativos.
    • % 2 contra a contagem() de números negativos retorna
    • --> 1 se houver um número ímpar de números negativos
    • --> 0 se houver um número par de números negativos
    • mais truques matemáticos:tiramos 1 ou 0 de 0,5, para que o acima se torne
    • --> (0.5-1=-0.5 =>arredondar para -1 ) se houver um número ímpar de números negativos
    • --> (0.5-0= 0.5 =>arredondar para 1 ) se houver um número par de números negativos
    • multiplicamos este 1/-1 final em relação ao valor SUM-PRODUCT para obter o resultado real