Por que não existe nenhuma função agregada do produto em SQL?

Estou à procura de algo parecido com SELECT PRODUCT(table.price) FROM table GROUP BY table.sale como SUM funciona.

Perdi alguma coisa na documentação, ou não há nenhuma função PRODUCT?

Em caso afirmativo, por que não?

Nota: procurei a função em postgres, mysql e mssql e não encontrei nenhuma, por isso assumi que toda a sql não a suporta.

Author: yoozer8, 2010-10-12

7 answers

Não existe nenhuma função PRODUCT definida na norma SQL. It would appear to be a worthy candidate, though (unlike, say, a CONCATENATE set function: it's not a good fit for SQL e.g. the resulting data type would involve multivalues and pose a problem as regards first normal form).

As normas SQL visam consolidar a funcionalidade em todos os produtos SQL por volta de 1990 e proporcionar uma "liderança de pensamento" no desenvolvimento futuro. Em resumo, eles documentam o que SQL faz e o que SQL deve fazer. A ausência de {[[0]} função de conjunto sugere que em 1990 nenhum fornecedor que merecesse ser incluído e não houve interesse académico em introduzi-lo no padrão.

É claro que os vendedores sempre procuraram adicionar a sua própria funcionalidade, hoje em dia normalmente como extensões aos padrões e não tangencialmente. Não me lembro de ver uma função de ajuste (ou mesmo demanda por uma) em qualquer um dos produtos SQL que eu usei.

Em todo o caso, o trabalho em torno é bastante simples usando log e exp funções escalar (e lógica para lidar com negativos) com a função SUM definir; veja a resposta de @gbn para algum código de exemplo. Nunca precisei de fazer isto numa candidatura a um negócio.

Em conclusão, meu melhor palpite é que não há demanda de SQL usuários finais para um PRODUCT definir a função; ainda mais, que qualquer pessoa com um interesse acadêmico provavelmente iria encontrar a solução aceitável (i.e. não teria valor a um açúcar sintático PRODUCT conjunto função fornecer).

Por interesse, há realmente demanda em terra do servidor SQL para novas funções de conjunto, mas para as da variedade de função janela (e SQL padrão, também). Para mais detalhes, incluindo como se envolver em mais demanda de condução, veja o blog de Itzik Ben-Gan .

 25
Author: onedaywhen, 2010-10-12 08:15:55

Para o MSSQL pode usar isto. Ele pode ser adotado para outras plataformas: é apenas matemática e agregados em 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

Retirado da minha resposta aqui: SQL Server Query-groupwise multiplication

 47
Author: gbn, 2017-05-23 12:18:00

Eu não sei porque não há um, mas (tome mais cuidado com os números negativos) você pode usar logs e expoentes para fazer: -

select exp (sum (ln (table.price))) from table ...
 15
Author: Lord Peter, 2010-10-12 06:50:45
Pode executar uma função agregada do produto, mas tem de ser você a fazer as contas, assim...
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

Fonte: http://productfunctionsql.codeplex.com/

 8
Author: user75525, 2010-10-12 06:47:50

Existe um truque fixe em T-SQL (não sei se é ANSI) que permite concatenar os valores de cadeia de um conjunto de linhas em uma variável. Parece que funciona para multiplicar também:

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

Isto pode ser potencialmente mais estável numericamente do que a solução log/exp.

 5
Author: David Airapetyan, 2013-06-20 15:27:13
Acho que é porque nenhum sistema de numeração é capaz de acomodar muitos produtos. Como as bases de dados são projetadas para um grande número de registros, um produto de 1000 números seria super massivo e no caso de números de ponto flutuante, o erro propagado seria enorme.

Note também que a utilização do log pode ser uma solução perigosa. Embora matematicamente log(a*b) = log(a)*log (b), pode não estar em computadores, pois não estamos lidando com números reais. Se calcular 2^[log(a)+log (b)] em vez de A*b, você pode obter resultados inesperados. Por exemplo:

SELECCIONAR 9999999999*999999974482, EXP (LOG (9999999999)+LOG (99999999974482))

No SQL Server devolve

99999999999644820000025518, 9.99999999644812 e + 23

Então o meu ponto é quando você está tentando fazer o produto com cuidado e teste é pesado.
 3
Author: naiem, 2012-01-18 02:59:54

Uma maneira de lidar com este problema (se você está trabalhando em uma linguagem de scripting) é usar a função group_concat. Por exemplo, SELECT group_concat(table.price) FROM table GROUP BY table.sale

Isto irá devolver um texto com todos os preços para o mesmo valor de venda, separado por uma vírgula. Então com um analisador você pode obter cada preço, e fazer uma multiplicação. (Em php você pode até mesmo usar a função array_ Reduce, de fato na php.net manual Você tem um exemplo adequado).

Saúde.
 1
Author: Nicolás Sierra, 2012-02-17 18:56:54