Operador agregado de mutiplicación en SQL

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í.

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

Por MUL ¿te refieres a la 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 scope de uso muy limitado, no necesita ser un estándar SQL. Como otros han demostrado, existen forms matemáticas de resolverlo, del mismo modo que hay muchas forms de hacer cálculos complicados en SQL simplemente usando methods estándar (y de uso común).

Data 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, 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))) 
  • Tenga cuidado al usar EXP / LOG en SQL Server, mire el tipo de devolución http://msdn.microsoft.com/en-us/library/ms187592.aspx
  • El formulario POWER permite numbers más grandes (usando bases más grandes que el número de Euler), y en casos donde el resultado crece demasiado grande como para regresar utilizando POWER, puede devolver solo 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, utilizando 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 

Ingnetworkingientes:

  • tomando los abs () de los datos, si el min es 0, multiplicando por lo que sea inútil, el resultado es 0
  • Cuando los datos son 0, NULLIF lo convierte en nulo. Los abs (), log () ambos 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 – llevaremos un logging de la negatividad en otro lugar
  • Elaborando el signo final
    • el signo (datos) devuelve 1 for >0 , 0 for 0 y -1 for <0 .
    • Añadimos otro 0.5 y tomamos el signo () nuevamente, por lo que ahora hemos clasificado 0 y 1 como 1, y solo -1 como -1.
    • de nuevo use NULLIF para eliminar de COUNT () los 1, ya que solo tenemos que contar los negativos.
    • % 2 contra el recuento () de numbers negativos devuelve
    • -> 1 si hay un número impar de numbers negativos
    • -> 0 si hay un número par de numbers negativos
    • más trucos matemáticos: tomamos 1 o 0 de 0.5, por lo que lo anterior se convierte
    • -> ( 0.5-1=-0.5 => networkingondo a -1 ) si hay un número impar de numbers negativos
    • -> ( 0.5-0= 0.5 => ronda a 1 ) si hay un número par de numbers negativos
    • multiplicamos este 1 / -1 final contra el valor SUM-PRODUCT para el resultado real

No, pero puedes usar Matemáticas 🙂

si yourColumn siempre es mayor que cero:

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

Veo que todavía falta una respuesta de Oracle, 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,
Robar.

Con PostgreSQL, puede crear sus propias funciones agregadas, consulte http://www.postgresql.org/docs/8.2/interactive/sql-createaggregate.html

Para crear una function agregada en MySQL, necesitará build un file .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.

Rompe cualquier tipo de datos con bastante rapidez a medida que aumentan los numbers.

Usar LOG / EXP es complicado debido a los numbers <= 0 que fallarán al usar LOG. Escribí una solución en esta pregunta que trata sobre esto

Usando 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 

No estoy seguro acerca de Oracle o sql-server, pero en MySQL puede 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)