2010-10-12 5 views
40

Estoy buscando algo así como SELECT PRODUCT(table.price) FROM table GROUP BY table.sale similar a cómo funciona SUM.¿Por qué no hay ninguna función de agregado de PRODUCT en SQL?

¿He omitido algo en la documentación o realmente no hay una función PRODUCT?

Si es así, ¿por qué no?

Nota: Busqué la función en postgres, mysql y mssql y no encontré ninguna, así que asumí que sql no la admite.

+1

Supongo que es mucho más raro querer calcular el producto en un conjunto de números que una suma. Incluso en su ejemplo, ¿con qué frecuencia desea calcular el producto de un conjunto de precios? –

+1

¿Cuál es el valor del producto (table.price) que se supone que debe responder? Al leer la "función de agregado de producto", entiendo que es para devolver el producto de todos los valores de tabla.precio encontrados en el conjunto de resultados: Row1.Price * Row2.Price * ... * RowN.Price. Pero por mi vida, no entiendo qué significa ese valor ", ¿qué información se supone que debe transmitir? ¿Cuál es la aplicación práctica de esto, para los precios o cualquier otro tipo de valor? Por favor iluminame. –

+4

para mi caso no es en realidad por precios, sino por obtener un producto de rendimientos (qty_out/qty_in). – lock

Respuesta

24

no hay ninguna función PRODUCT conjunto en el estándar SQL. Sin embargo, parece ser un candidato digno (a diferencia de, digamos, una función de conjunto CONCATENATE: no es una buena opción para SQL, por ejemplo, el tipo de datos resultante involucraría multivalos y plantearía un problema con respecto a la primera forma normal).

Los estándares SQL tienen como objetivo consolidar la funcionalidad de los productos SQL alrededor de 1990 y proporcionar un "liderazgo de pensamiento" en el desarrollo futuro. En resumen, documentan lo que SQL hace y lo que SQL debe hacer. La ausencia de la función de conjunto PRODUCT sugiere que, en 1990, ningún proveedor era digno de ser incluido y que no ha habido interés académico en introducirlo en el Estándar.

Por supuesto, los vendedores siempre han intentado agregar su propia funcionalidad, actualmente como extensiones a estándares en lugar de tangentally. No recuerdo haber visto una función de configuración PRODUCT (o incluso la demanda de una) en ninguno de los productos SQL que he usado.

En cualquier caso, el trabajo es bastante simple usando log y exp funciones escalares (y lógica para manejar negativos) con la función de conjunto SUM; ver la respuesta de @gbn para un código de muestra. Sin embargo, nunca tuve que hacer esto en una aplicación de negocios.

En conclusión, mi mejor estimación es que no hay demanda por parte de los usuarios finales de SQL para una función de conjunto PRODUCT; además, que cualquier persona con un interés académico probablemente encontraría la solución alternativa aceptable (es decir, no valoraría el azúcar sintáctico que proporcionaría una función de conjunto PRODUCT).

Fuera de interés, de hecho hay demanda en SQL Server Land para nuevas funciones de conjunto pero para aquellas de la variedad de funciones de ventana (y Standard SQL, también). Para obtener más detalles, incluido cómo participar en la demanda de conducción adicional, consulte Itzik Ben-Gan's blog.

+2

+1 "No hay ninguna función de conjunto de PRODUCT en el estándar SQL. Aunque parece ser un candidato digno", también lo haría una función de media geométrica. –

+0

Desafortunadamente esta respuesta es bastante incorrecta. exp (sum (log (column)) funciona muy bien para números positivos o ver las mejores respuestas a continuación. – Chris

+0

Marca, la media geográfica es la siguiente: exp (avg (log (x))) – Chris

7

Se puede realizar una función de agregado del producto, pero hay que hacer las cuentas a sí mismo, así ...

SELECT 
    Exp(Sum(IIf(Abs([Num])=0,0,Log(Abs([Num])))))*IIf(Min(Abs([Num]))=0,0,1)*(1-2*(Sum(IIf([Num]>=0,0,1)) Mod 2)) AS P 
FROM 
    Table1 

Fuente: http://productfunctionsql.codeplex.com/

14

No sé por qué no hay uno, pero (tener más cuidado sobre los números negativos) de utilizar los registros y exponentes que hacer: -

select exp (sum (ln (table.price))) from table ... 
+2

Añadir redonda() si se está calculando el producto de los valores de una columna entera. a veces el 0,9999 ... se devuelve en lugar de toda una int. – inam101

45

para MSSQL se puede utilizar este. Puede ser adoptado para otras plataformas: es solo matemática y agrega logaritmos.

SELECT 
    GrpID, 
    CASE 
     WHEN MinVal = 0 THEN 0 
     WHEN Neg % 2 = 1 THEN -1 * EXP(ABSMult) 
     ELSE EXP(ABSMult) 
    END 
FROM 
    (
    SELECT 
     GrpID, 
     --log of +ve row values 
     SUM(LOG(ABS(NULLIF(Value, 0)))) AS ABSMult, 
     --count of -ve values. Even = +ve result. 
     SUM(SIGN(CASE WHEN Value < 0 THEN 1 ELSE 0 END)) AS Neg, 
     --anything * zero = zero 
     MIN(ABS(Value)) AS MinVal 
    FROM 
     Mytable 
    GROUP BY 
     GrpID 
    ) foo 

tomado de mi respuesta aquí: SQL Server Query - groupwise multiplication

+4

"es sólo matemáticas y agregados en logaritmos" :) 'log (a * b * c ... * n) = log (a) + log (b) + log (c) ... + log (n) ' – onedaywhen

+3

en serio @gbn, eres el hombre. – FistOfFury

3

Creo que es porque ningún sistema de numeración puede acomodar muchos productos.Como las bases de datos están diseñadas para una gran cantidad de registros, un producto de 1000 números sería súper masivo y, en el caso de números en coma flotante, el error propagado sería enorme.

También tenga en cuenta que el uso de registro puede ser una solución peligrosa. Aunque matemáticamente log (a * b) = log (a) * log (b), podría no estar en las computadoras ya que no estamos tratando con números reales. Si calcula 2^(log (a) + log (b)) en lugar de a * b, puede obtener resultados inesperados. Por ejemplo:

SELECT * 9999999999 99999999974482, EXP (LOG (9999999999) + log (99999999974482))

en SQL Server devuelve

999999999644820000025518, 9.99999999644812E + 23

Así que mi punto es cuando intenta hacer el producto, hágalo con cuidado y la prueba es pesada.

1

Una forma de resolver este problema (si está trabajando en un lenguaje de scripting) es usar la función group_concat. Por ejemplo, SELECT group_concat(table.price) FROM table GROUP BY table.sale

Esto devolverá una cadena con todos los precios para el mismo valor de venta, separados por una coma. Luego, con un analizador puede obtener cada precio y hacer una multiplicación. (En php incluso puedes usar la función array_reduce, de hecho, en el php.net manual obtienes un ejemplo adecuado).

Saludos

5

Hay un truco de T-SQL (no estoy seguro si es ANSI) que permite concatenar los valores de cadena de un conjunto de filas en una variable. Parece que funciona para multiplicar también:

declare @Floats as table (value float) 
insert into @Floats values (0.9) 
insert into @Floats values (0.9) 
insert into @Floats values (0.9) 

declare @multiplier float = null 

select 
    @multiplier = isnull(@multiplier, '1') * value 
from @Floats 

select @multiplier 

Esto puede ser potencialmente más numéricamente estable que la solución de registro/exp.

+0

¡Increíble! ¡Gracias! –

Cuestiones relacionadas