2011-03-24 13 views
22

En SQL hay operadores de agregación, como AVG, SUM, COUNT. ¿Por qué no tiene un operador para la multiplicación? "MUL" o algo así.Operador agregado de mutiplicación en SQL

Me preguntaba si existe para Oracle, MSSQL, MySQL? Si no, ¿hay una solución que daría este comportamiento?

+3

http://stackoverflow.com/questions/5218375/aggregate-multiplicate-function/5219216#5219216 --- solución difícil basada en las matemáticas. – zerkms

+0

posible duplicado de [¿hay una función de PRODUCTO como si hubiera una función SUMA en Oracle SQL?] (Http://stackoverflow.com/questions/403924/is-there-a-product-function-like-there-is- a-sum-function-in-oracle-sql) – onedaywhen

+0

@onedaywhen - la respuesta aceptada no funciona para 0/<0 números. Además, OP intenta cubrir 3 DBMS en una pregunta. duplicado "exacto" es un tramo – RichardTheKiwi

Respuesta

35

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

Incluso con 100 filas de tamaño pequeño (digamos 10s), su MUL (columna) se desbordará en cualquier tipo de datos. Con una alta probabilidad de uso incorrecto/ab, y un alcance de uso muy limitado, no necesita ser un estándar SQL. Como otros han demostrado, existen formas matemáticas de resolverlo, del mismo modo que hay muchas formas de hacer cálculos complicados en SQL simplemente usando métodos estándar (y de uso común).

datos

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, el Oracle, MSSQL, MySQL núcleo implementaciones *

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 utilizar CAD/LOG en SQL Server, ver el tipo de retorno http://msdn.microsoft.com/en-us/library/ms187592.aspx
  • La forma de ENERGÍA permite números más grandes (usando bases más grandes que el número de Euler), y en casos donde el resultado crece demasiado grande para vuelva a usar energía, puede devolver sólo el valor logarítmico y calcular el número real fuera de la consulta SQL


* log (0) y log (-ve) no están definidos. A continuación, solo se muestra cómo manejar esto en SQL Server. Equivalentes se pueden encontrar para los otros sabores 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:

  • que toman la abs() de datos, si el min es 0, multiplicando por cualquier otra cosa que sea inútil, el resultado es 0
  • Cuando los datos son 0, NULLIF lo convierte en nulo. Los valores abs(), log() devuelven nulo, lo que impide su suma()
  • Si los datos no son 0, abs nos permite multiplicar un número negativo utilizando el método LOG - realizaremos un seguimiento de la negatividad en otros lugares
  • Averiguar el signo final
    • señal (datos) devuelve 1 for >0, 0 for 0 y -1 for <0.
    • Añadimos otro 0.5 y tomamos nuevamente el signo(), por lo que ahora hemos clasificado 0 y 1 como 1 y solo -1 como -1.
    • utilizamos NULLIF para eliminar de COUNT() los 1, ya que solo tenemos que contar los negativos.
    • % 2 contra el conde() devuelve los números negativos, ya sea
    • -> 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: se toman 1 o 0 fuera de 0,5, por lo que lo anterior se convierte en
    • -> (0.5-1=-0.5 => ronda de -1) si hay un número impar de números negativos
    • -> (0.5-0= 0.5 => ronda a) si hay un número par de números negativos
    • que múltiples esta final 1/-1 contra el valor de suma-producto para el resultado real de
+0

Vea esto para diferentes formas de manejo cero y negativo: http://stackoverflow.com/questions/3653586 – gbn

+0

Para evitar advertencias ANSI sobre los valores NULL que se eliminan del operador agregado o SET, puede reemplazar 'count (nullif (sign (data) +0.5), 1))' by 'COUNT (CASE WHEN SIGN (SIGN (data) +0.5) < > 1 LUEGO 1 FIN) '.También puede 'CONFIGURAR ANSI_WARNINGS OFF' antes de ejecutar la consulta, pero prefiero escribir la consulta para que no produzca advertencias en primer lugar. –

+0

Curiosamente, el NULLIF (datos, 0) en 'EXP (SUMA (Log (abs (nullif (data, 0)))))' es necesario para que funcione, aunque la sentencia CASE debería devolver 0 sin evaluar el ELSE parte. Si hay valores cero en el conjunto de datos, omitir el NULLIF (datos, 0) da como resultado un error de dominio. –

-1

No estoy seguro acerca de Oracle o sql-server, pero en MySQL puede simplemente usar * como lo haría normalmente.

mysql> select count(id), count(id)*10 from tablename; 
+-----------+--------------+ 
| count(id) | count(id)*10 | 
+-----------+--------------+ 
|  961 |   9610 | 
+-----------+--------------+ 
1 row in set (0.00 sec) 
20

No, pero se pueden usar las matemáticas :)

si yourColumn es siempre mayor que cero:

select EXP(SUM(LOG(yourColumn))) As ColumnProduct from yourTable 
+0

Konerak EXP *** es *** 'e'. http://msdn.microsoft.com/en-us/library/ms179857.aspx. Es el EXP-onent del registro natural, que se empareja con LOG – RichardTheKiwi

+0

-1 "ORA-00909: número de argumentos no válido". EDITAR: Oops, veo que no es una pregunta solo de Oracle ... He deshecho mi -1. –

1

con PostgreSQL, puede crear sus propias funciones de agregación, consulte

Para crear una función agregada en MySQL, necesitará construir un archivo .so (linux) o .dll (windows). Aquí se muestra un ejemplo: http://www.codeproject.com/KB/database/mygroupconcat.aspx

No estoy seguro acerca de mssql y oracle, pero apuesto a que tienen opciones para crear agregados personalizados también.

6

veo una respuesta de Oracle sigue desaparecido, así que aquí está:

SQL> with yourTable as 
    2 (select 1 yourColumn from dual union all 
    3 select 2 from dual union all 
    4 select 4 from dual union all 
    5 select 8 from dual 
    6 ) 
    7 select EXP(SUM(LN(yourColumn))) As ColumnProduct from yourTable 
    8/

COLUMNPRODUCT 
------------- 
      64 

1 row selected. 

Saludos,
Rob.

1

Romperá cualquier tipo de datos con bastante rapidez a medida que se acumulen los números.

El uso de LOG/EXP es complicado debido a los números < = 0 que fallarán al usar LOG. Escribí una solución en this question que se ocupa de este

0

El uso de CTE en MS SQL:

CREATE TABLE Foo(Id int, Val int) 
INSERT INTO Foo VALUES(1, 2), (2, 3), (3, 4), (4, 5), (5, 6) 

;WITH cte AS 
(
    SELECT Id, Val AS Multiply, row_number() over (order by Id) as rn 
    FROM Foo 
    WHERE Id=1 
    UNION ALL 
    SELECT ff.Id, cte.multiply*ff.Val as multiply, ff.rn FROM 
    (SELECT f.Id, f.Val, (row_number() over (order by f.Id)) as rn 
    FROM Foo f) ff 
     INNER JOIN cte 
     ON ff.rn -1= cte.rn 
) 
SELECT * FROM cte