Bedoelt u met MUL progressieve vermenigvuldiging van waarden?
Zelfs met 100 rijen van een klein formaat (zeg 10s), zal je MUL (kolom) elk gegevenstype overlopen! Met zo'n grote kans op misbruik en zeer beperkte gebruiksmogelijkheden, hoeft het geen SQL-standaard te zijn. Zoals anderen hebben aangetoond, zijn er wiskundige manieren om het uit te werken, net zoals er veel manieren zijn om lastige berekeningen in SQL uit te voeren door alleen standaard (en veelgebruikte) methoden te gebruiken.
Voorbeeldgegevens:
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 )
Voor de volledigheid, de kernimplementaties van 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)))
- Let op bij het gebruik van EXP/LOG in SQL Server, let op het retourtype http://msdn.microsoft.com/en-us/library/ms187592.aspx
- Het POWER-formulier staat grotere getallen toe (gebruikmakend van basen groter dan het getal van Euler), en in gevallen waarin het resultaat te groot wordt om het terug te draaien met POWER, kun je alleen de logaritmische waarde retourneren en het werkelijke getal berekenen buiten de SQL-query
* LOG(0) en LOG(-ve) zijn niet gedefinieerd. Het onderstaande laat alleen zien hoe dit in SQL Server moet worden afgehandeld. Er kunnen equivalenten worden gevonden voor de andere SQL-smaken, met hetzelfde concept
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
Ingrediënten:
- het nemen van de abs() van gegevens, als de min 0 is, vermenigvuldigen met wat verder zinloos is, is het resultaat 0
- Als gegevens 0 zijn, converteert NULLIF deze naar null. De abs(), log() retourneren beide null, waardoor het wordt uitgesloten van sum()
- Als de gegevens niet 0 zijn, kunnen we met abs een negatief getal vermenigvuldigen met behulp van de LOG-methode - we houden de negativiteit elders bij
- Het laatste teken uitwerken
- sign(data) retourneert
1 for >0
,0 for 0
en-1 for <0
. - We voegen nog een 0,5 toe en nemen opnieuw het teken(), dus we hebben nu 0 en 1 beide geclassificeerd als 1, en alleen -1 als -1.
- gebruik opnieuw NULLIF om de enen van COUNT() te verwijderen, aangezien we alleen de minpunten hoeven op te tellen.
% 2
tegen de telling() van negatieve getallen retourneert ofwel- --> 1 als er een oneven aantal negatieve getallen is
- --> 0 als er een even aantal negatieve getallen is
- meer wiskundige trucs:we nemen 1 of 0 van 0,5, zodat het bovenstaande wordt
- --> (
0.5-1=-0.5
=>rond af op -1 ) als er een oneven aantal negatieve getallen is - --> (
0.5-0= 0.5
=>rond af op 1 ) als er een even aantal negatieve getallen is - we vermenigvuldigen deze laatste 1/-1 met de SOM-PRODUCT-waarde voor het echte resultaat
- sign(data) retourneert