sql >> Base de Datos >  >> RDS >> Sqlserver

Operador agregado de multiplicación en SQL

¿Por MUL te refieres a la multiplicación progresiva de valores?

¡Incluso con 100 filas de un tamaño pequeño (digamos 10), su MUL (columna) desbordará cualquier tipo de datos! Con una probabilidad tan alta de uso indebido/abuso y un ámbito de uso muy limitado, no es necesario que sea un estándar SQL. Como otros han demostrado, hay formas matemáticas de resolverlo, al igual que hay muchas formas de hacer cálculos complicados en SQL simplemente usando métodos estándar (y de uso común).

Datos de muestra:

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, las implementaciones principales de Oracle, MSSQL y 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 al usar EXP/LOG en SQL Server, observe el tipo de devolución http://msdn.microsoft.com/en-us/library/ms187592.aspx
  • La forma POWER permite números más grandes (utilizando bases más grandes que el número de Euler) y, en los casos en que el resultado sea demasiado grande como para volver a utilizar POWER, puede devolver solo el valor logarítmico y calcular el número real fuera del Consulta SQL

* LOG(0) y LOG(-ve) no están definidos. A continuación se muestra solo cómo manejar esto en SQL Server. Se pueden encontrar equivalentes para los otros sabores de SQL, usando el mismo concepto

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:

  • tomando el abs() de datos, si el mínimo es 0, multiplicando por cualquier otra cosa es inútil, el resultado es 0
  • Cuando los datos son 0, NULLIF los convierte en nulos. Abs(), log() devuelven nulo, lo que hace que se excluya de sum()
  • Si los datos no son 0, abs nos permite multiplicar un número negativo usando el método LOG; realizaremos un seguimiento de la negatividad en otro lugar
  • Desarrollando el signo final
    • sign(data) devuelve 1 for >0 , 0 for 0 y -1 for <0 .
    • Añadimos otro 0,5 y volvemos a tomar el signo(), por lo que ahora hemos clasificado 0 y 1 como 1, y solo -1 como -1.
    • nuevamente use NULLIF para eliminar de COUNT() los 1, ya que solo necesitamos contar los negativos.
    • % 2 contra el recuento () de números negativos devuelve
    • --> 1 si hay un número impar de números negativos
    • --> 0 si hay un número par de números negativos
    • más trucos matemáticos:quitamos 1 o 0 de 0,5, de modo que lo anterior se convierte en
    • --> (0.5-1=-0.5 =>redondear a -1 ) si hay un número impar de números negativos
    • --> (0.5-0= 0.5 =>redondear a 1 ) si hay un número par de números negativos
    • multiplicamos este 1/-1 final contra el valor SUMA-PRODUCTO para el resultado real