sql >> Database teknologi >  >> RDS >> Sqlserver

Multiplikationsaggregatoperator i SQL

Med MUL mener du progressiv multiplikation af værdier?

Selv med 100 rækker af en eller anden lille størrelse (f.eks. 10s), vil din MUL(kolonne) løbe over enhver datatype! Med så stor en sandsynlighed for misbrug og meget begrænset anvendelsesmuligheder, behøver det ikke at være en SQL-standard. Som andre har vist, er der matematiske måder at regne det ud på, ligesom der er mange mange måder at lave vanskelige beregninger i SQL ved blot at bruge standardmetoder (og almindeligt anvendte) metoder.

Eksempeldata:

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 )

For fuldstændighedens skyld, Oracle, MSSQL, MySQL kerneimplementeringerne *

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)))
  • Forsigtig, når du bruger EXP/LOG i SQL Server, vær opmærksom på returtypen http://msdn.microsoft.com/en-us/library/ms187592.aspx
  • POWER-formularen giver mulighed for større tal (ved at bruge baser større end Eulers tal), og i tilfælde, hvor resultatet bliver for stort til at slå det tilbage ved hjælp af POWER, kan du kun returnere den logaritmiske værdi og beregne det faktiske tal uden for SQL-forespørgsel

* LOG(0) og LOG(-ve) er udefinerede. Nedenstående viser kun, hvordan man håndterer dette i SQL Server. Ækvivalenter kan findes for de andre SQL-varianter, der bruger det samme koncept

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

Ingredienser:

  • ved at tage abs() af data, hvis min er 0, ganget med alt andet der er nyttesløst, er resultatet 0
  • Når data er 0, konverterer NULLIF det til null. abs(), log() returnerer begge null, hvilket får den til at blive udelukket fra sum()
  • Hvis data ikke er 0, giver abs os mulighed for at multiplicere et negativt tal ved hjælp af LOG-metoden - vi holder styr på negativiteten andre steder
  • Udarbejdelse af det sidste tegn
    • tegn(data) returnerer 1 for >0 , 0 for 0 og -1 for <0 .
    • Vi tilføjer yderligere 0,5 og tager tegnet() igen, så vi har nu klassificeret 0 og 1 både som 1 og kun -1 som -1.
    • brug igen NULLIF til at fjerne 1'erne fra COUNT(), da vi kun behøver at tælle negativerne op.
    • % 2 mod count() af negative tal returnerer enten
    • --> 1 hvis der er et ulige antal negative tal
    • --> 0, hvis der er et lige antal negative tal
    • flere matematiske tricks:vi tager 1 eller 0 fra 0,5, så ovenstående bliver
    • --> (0.5-1=-0.5 =>rund til -1 ) hvis der er et ulige antal negative tal
    • --> (0.5-0= 0.5 =>rund til 1 ) hvis der er et lige antal negative tal
    • vi multiplicerer denne sidste 1/-1 mod SUM-PRODUCT-værdien for det reelle resultat


  1. 5 MySql nyttige forespørgsler under projektudvikling

  2. NVL2-funktion i Oracle

  3. Kun backup af SQL-skema?

  4. 12c Forældede funktioner