Theo hiểu biết tốt nhất của tôi, không có. Viết một cái là khá đơn giản, mặc dù. Phần sau cung cấp cho bạn hệ số alpha và beta độ dốc không đổi cho y =Alpha + Beta * x + epsilon:
-- test data (GroupIDs 1, 2 normal regressions, 3, 4 = no variance)
WITH some_table(GroupID, 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
UNION SELECT 2, 60, 70 UNION SELECT 3, 1, 2 UNION SELECT 3, 1, 3
UNION SELECT 4, 1, 2 UNION SELECT 4, 2, 2),
-- linear regression query
/*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() implementation is not numerically stable
,CASE SUM(SQUARE(x - xmean)) WHEN 0 THEN 1
ELSE SQRT(SUM(SQUARE(x - xmean)) / (COUNT(*) - 1)) END AS 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 -- increases numerical stability
( SELECT pd.GroupID
,(x - xmean) / xstdev AS xstd
,CASE ystdev WHEN 0 THEN 0 ELSE (y - ymean) / ystdev END AS ystd
FROM some_table pd
INNER JOIN stdev_estimates ps 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(xstd * ystd) / (COUNT(*) - 1) END AS betastd
FROM standardized_data pd
GROUP BY GroupID
)
SELECT pb.GroupID
,ymean - xmean * betastd * ystdev / xstdev AS Alpha
,betastd * ystdev / xstdev AS Beta
FROM standardized_beta_estimates pb
INNER JOIN stdev_estimates ps ON ps.GroupID = pb.GroupID
INNER JOIN mean_estimates pm ON pm.GroupID = pb.GroupID
Đây GroupID
được sử dụng để hiển thị cách nhóm theo một số giá trị trong bảng dữ liệu nguồn của bạn. Nếu bạn chỉ muốn thống kê trên tất cả dữ liệu trong bảng (không phải các nhóm con cụ thể), bạn có thể loại bỏ nó và các kết hợp. Tôi đã sử dụng WITH
tuyên bố vì lợi ích của sự rõ ràng. Thay vào đó, bạn có thể sử dụng các truy vấn phụ. Hãy lưu ý đến độ chính xác của loại dữ liệu được sử dụng trong các bảng của bạn vì độ ổn định số có thể giảm đi nhanh chóng nếu độ chính xác không đủ cao so với dữ liệu của bạn.
CHỈNH SỬA: (trả lời câu hỏi của Peter để biết thêm số liệu thống kê như R2 trong phần nhận xét)
Bạn có thể dễ dàng tính toán các số liệu thống kê bổ sung bằng cách sử dụng cùng một kỹ thuật. Đây là phiên bản có R2, tương quan và hiệp phương sai mẫu:
-- test data (GroupIDs 1, 2 normal regressions, 3, 4 = no variance)
WITH some_table(GroupID, 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
UNION SELECT 2, 60, 70 UNION SELECT 3, 1, 2 UNION SELECT 3, 1, 3
UNION SELECT 4, 1, 2 UNION SELECT 4, 2, 2),
-- linear regression query
/*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() implementation is not numerically stable
,CASE SUM(SQUARE(x - xmean)) WHEN 0 THEN 1
ELSE SQRT(SUM(SQUARE(x - xmean)) / (COUNT(*) - 1)) END AS 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 -- increases numerical stability
( SELECT pd.GroupID
,(x - xmean) / xstdev AS xstd
,CASE ystdev WHEN 0 THEN 0 ELSE (y - ymean) / ystdev END AS ystd
FROM some_table pd
INNER JOIN stdev_estimates ps 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(xstd * ystd) / (COUNT(*) - 1) END AS betastd
FROM standardized_data
GROUP BY 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 Covar
FROM standardized_beta_estimates pb
INNER JOIN stdev_estimates ps ON ps.GroupID = pb.GroupID
INNER JOIN mean_estimates pm ON pm.GroupID = pb.GroupID
CHỈNH SỬA 2 cải thiện độ ổn định số bằng cách chuẩn hóa dữ liệu (thay vì chỉ căn giữa) và bằng cách thay thế STDEV
vì vấn đề ổn định số
. Đối với tôi, việc triển khai hiện tại dường như là sự cân bằng tốt nhất giữa tính ổn định và sự phức tạp. Tôi có thể cải thiện độ ổn định bằng cách thay thế độ lệch chuẩn của mình bằng một thuật toán trực tuyến ổn định về số, nhưng điều này sẽ làm phức tạp đáng kể việc triển khai (và làm chậm nó). Tương tự, các triển khai bằng cách sử dụng ví dụ:Kahan (-Babuška-Neumaier) đền bù cho SUM
và AVG
dường như hoạt động tốt hơn một cách khiêm tốn trong các thử nghiệm hạn chế, nhưng làm cho truy vấn phức tạp hơn nhiều. Và miễn là tôi không biết cách T-SQL triển khai SUM
và AVG
(ví dụ:nó có thể đã sử dụng tính toán tổng hợp theo cặp), tôi không thể đảm bảo rằng những sửa đổi đó luôn cải thiện độ chính xác.