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