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

Er der nogen lineær regressionsfunktion i SQL Server?

Så vidt jeg ved, er der ingen. At skrive en er dog ret ligetil. Følgende giver dig den konstante alfa- og hældningsbeta for y =Alpha + Beta * x + epsilon:

-- testdata (GruppeID 1, 2 normale regressioner, 3, 4 =ingen varians) MED some_table(GruppeID, x, y) AS( SELECT 1, 1, 1 UNION SELECT 1, 2, 2 UNION SELECT 1, 3, 1.3 UNION SELECT 1, 4, 3.75 UNION SELECT 1, 5, 2.25 UNION SELECT 2, 95, 85 UNION SELECT 2, 85, 95 UNION SELECT 2, 80, 70 UNION SELECT 2, 70, 65 2, 60, 70 UNION SELECT 3, 1, 2 UNION SELECT 3, 1, 3 UNION SELECT 4, 1, 2 UNION SELECT 4, 2, 2), -- lineær regressionsforespørgsel/*WITH*/ mean_estimates AS( SELECT GroupID ,AVG(x * 1.) AS xmean ,AVG(y * 1.) AS ymean FROM some_table GROUP BY GroupID),stdev_estimates AS( SELECT pd.GroupID -- T-SQL STDEV() implementering er ikke numerisk stabil ,CASE SUM (KVADRAT(x - xmiddel)) NÅR 0 SÅ 1 ANDET SQRT(SUM(KVADRA(x - xmiddel)) / (ANTAL(*) - 1)) SLUT SOM xstdev , SQRT( SUM(SQUARE(y - ymean)) / (COUNT(*) - 1)) AS ystdev FROM some_table pd INNER JOIN mean_estimates pm ON pm.GroupID =pd.GroupID GROUP BY pd.GroupID, pm.xmean, pm.ymean) ,standardized_data AS -- øger numerisk stabilitet( SELECT pd.GroupID ,(x - xmean) / xstdev AS xstd ,CASE ystdev WHEN 0 THEN 0 ELSE (y - ymean) / ystdev END AS ystd FROM some_tables pd INNER JOIMIN .GroupID =pd.GroupID INNER JOIN mean_estimates pm ON pm.GroupID =pd.GroupID),standardized_beta_estimates AS( SELECT GroupID ,CASE WHEN SUM(xstd * xstd) =0 THEN 0 ELSE SUM(xstd) /COUNT(*ystd) ) - 1) AFSLUT SOM betastd FRA standardized_data pd GROUP BY GroupID)SELECT pb.GroupID ,ymean - xmean * betastd * ystdev / xstdev AS Alpha ,betastd * ystdev / xstdev AS BetaFROM standardized_beta_estimates pbINNER JOIN stdev_estimates ps ON ps.GroupID =pb.GroupIDINNER JOIN mean_estimates pm ON pm.GroupID =pb.GroupID

Her GruppeID bruges til at vise, hvordan man grupperer efter en eller anden værdi i din kildedatatabel. Hvis du blot vil have statistikken på tværs af alle data i tabellen (ikke specifikke undergrupper), kan du droppe den og joins. Jeg har brugt WITH redegørelse for overskuelighedens skyld. Som et alternativ kan du i stedet bruge underforespørgsler. Vær opmærksom på præcisionen af ​​den datatype, der bruges i dine tabeller, da den numeriske stabilitet kan forringes hurtigt, hvis præcisionen ikke er høj nok i forhold til dine data.

EDIT: (som svar på Peters spørgsmål for yderligere statistik som R2 i kommentarerne)

Du kan nemt beregne yderligere statistik ved hjælp af samme teknik. Her er en version med R2, korrelation og prøve kovarians:

-- testdata (GruppeID 1, 2 normale regressioner, 3, 4 =ingen varians) MED some_table(GruppeID, x, y) AS( SELECT 1, 1, 1 UNION SELECT 1, 2, 2 UNION SELECT 1, 3, 1.3 UNION SELECT 1, 4, 3.75 UNION SELECT 1, 5, 2.25 UNION SELECT 2, 95, 85 UNION SELECT 2, 85, 95 UNION SELECT 2, 80, 70 UNION SELECT 2, 70, 65 2, 60, 70 UNION SELECT 3, 1, 2 UNION SELECT 3, 1, 3 UNION SELECT 4, 1, 2 UNION SELECT 4, 2, 2), -- lineær regressionsforespørgsel/*WITH*/ mean_estimates AS( SELECT GroupID ,AVG(x * 1.) AS xmean ,AVG(y * 1.) AS ymean FROM some_table pd GROUP BY GroupID),stdev_estimates AS( SELECT pd.GroupID -- T-SQL STDEV() implementering er ikke numerisk stabil ,CASE SUM(SQUARE(x - xmean)) WHEN 0 THEN 1 ELSE SQRT(SUM(SQUARE(x - xmean)) / (COUNT(*) - 1)) END AS xstdev , SQ RT(SUM(SQUARE(y - ymean)) / (COUNT(*) - 1)) AS ystdev FROM some_table pd INNER JOIN mean_estimates pm ON pm.GroupID =pd.GroupID GROUP BY pd.GroupID, pm.xmean, pm. ymean),standardized_data AS -- øger numerisk stabilitet( SELECT pd.GroupID ,(x - xmean) / xstdev AS xstd ,CASE ystdev WHEN 0 THEN 0 ELSE (y - ymean) / ystdev END AS ystd FROM some_tables pds INNER JOIMATES pddev ON ps.GroupID =pd.GroupID INNER JOIN mean_estimates pm ON pm.GroupID =pd.GroupID),standardized_beta_estimates AS( SELECT GroupID ,CASE WHEN SUM(xstd * xstd) =0 THEN 0 ELSE SUM(std) /COUNT. (*) - 1) AFSLUT SOM betastd FRA standardiserede_data GRUPPER EFTER GroupID)SELECT pb.GroupID ,ymean - xmean * betastd * ystdev / xstdev AS Alpha ,betastd * ystdev / xstdev AS Beta ,CASE ystdev WHEN 0 THEN 1 ELSE betastd * betastd END AS R2 ,betastd AS Correl ,betastd * xstdev * ystdev AS CovarFROM standardized_beta_estimates pbINNER JOIN stdev_estimates ps ON ps.GroupID =pb.GroupIDINNER JOIN mean_estimates PM ON pm.code

REDIGERING 2 forbedrer numerisk stabilitet ved at standardisere data (i stedet for kun at centrere) og ved at erstatte STDEV på grund af numeriske stabilitetsproblemer . For mig ser den nuværende implementering ud til at være den bedste afvejning mellem stabilitet og kompleksitet. Jeg kunne forbedre stabiliteten ved at erstatte min standardafvigelse med en numerisk stabil online-algoritme, men dette ville komplicere implementeringen væsentligt (og bremse den). Tilsvarende er implementeringer ved hjælp af f.eks. Kahan(-Babuška-Neumaier) kompensationer for SUM og AVG synes at præstere beskedent bedre i begrænsede test, men gør forespørgslen meget mere kompleks. Og så længe jeg ikke ved, hvordan T-SQL implementerer SUM og AVG (det kan f.eks. allerede bruge parvis summering), jeg kan ikke garantere, at sådanne ændringer altid forbedrer nøjagtigheden.



  1. hvordan vælger man lige poster fra en tabel i oracle?

  2. Hvad er forskellen mellem at bruge en krydssammenføjning og at sætte et komma mellem de to tabeller?

  3. Få MAX fra en GROUP BY

  4. Sådan henter du vært, port, sid, bruger og adgangskodeoplysninger i java.sql.Connection