使用SQL查找协方差
我有一个表,看起来像^(但有数百行,日期从2009年到2013年)。是否有一种方法可以计算协方差:[(使用SQL查找协方差,sql,sql-server,sql-server-2008,covariance,Sql,Sql Server,Sql Server 2008,Covariance,我有一个表,看起来像^(但有数百行,日期从2009年到2013年)。是否有一种方法可以计算协方差:[(indx_val1-avg(indx_val1)*(indx_val2-avg(indx_val2)]除以indx_val1和indx_val2)每个值的行总数(循环整个表格),然后返回cov的简单值(ABQI,ACNACTR)由于在两个不同的组上进行聚合操作,因此需要两个不同的查询。主要的一个查询按dt分组以获取每个日期的行值。另一个查询必须在整个行集中执行AVG()和COUNT()聚合 要同
indx_val1
-avg(indx_val1
)*(indx_val2
-avg(indx_val2
)]除以indx_val1
和indx_val2
)每个值的行总数(循环整个表格),然后返回cov的简单值(ABQI
,ACNACTR
)由于在两个不同的组上进行聚合操作,因此需要两个不同的查询。主要的一个查询按dt
分组以获取每个日期的行值。另一个查询必须在整个行集中执行AVG()
和COUNT()
聚合
要同时使用这两个查询,需要将它们连接在一起。但由于两个查询之间没有实际关系,因此这是笛卡尔积,我们将使用交叉连接。有效地,将主查询的每一行与聚合查询检索到的单行连接起来。然后可以执行算术运算在选择列表中,使用以下两个值:
因此,根据您前面问题的查询:
# dt---------indx_nm1-----indx_val1-------indx_nm2------indx_val2
2009-06-08----ABQI------1001.2------------ACNACTR----------300.05
2009-06-09----ABQI------1002.12 ----------ACNACTR----------341.19
2009-06-10----ABQI------1011.4------------ACNACTR----------382.93
2009-06-11----ABQI------1015.43 ----------ACNACTR----------362.63
这是一个演示,建立在您前面的基础上:这是一个标量值函数,用于对格式化为XML的任何两列表执行协方差计算
测试:编译函数,然后执行Alpha测试
SELECT
indxs.*,
((indx_val2 - indx_val2_avg) * (indx_val1 - indx_val1_avg)) / total_rows AS cv
FROM (
SELECT
dt,
MAX(CASE WHEN indx_nm = 'ABQI' THEN indx_nm ELSE NULL END) AS indx_nm1,
MAX(CASE WHEN indx_nm = 'ABQI' THEN indx_val ELSE NULL END) AS indx_val1,
MAX(CASE WHEN indx_nm = 'ACNACTR' THEN indx_nm ELSE NULL END) AS indx_nm2,
MAX(CASE WHEN indx_nm = 'ACNACTR' THEN indx_val ELSE NULL END) AS indx_val2
FROM table1 a
GROUP BY dt
) indxs
CROSS JOIN (
/* Join against a query returning the AVG() and COUNT() across all rows */
SELECT
'ABQI' AS indx_nm1_aname,
AVG(CASE WHEN indx_nm = 'ABQI' THEN indx_val ELSE NULL END) AS indx_val1_avg,
'ACNACTR' AS indx_nm2_aname,
AVG(CASE WHEN indx_nm = 'ACNACTR' THEN indx_val ELSE NULL END) AS indx_val2_avg,
COUNT(*) AS total_rows
FROM table1 b
WHERE indx_nm IN ('ABQI','ACNACTR')
/* And it is a cartesian product */
) aggs
WHERE
indx_nm1 IS NOT NULL
AND indx_nm2 IS NOT NULL
ORDER BY dt
好的,谢谢你的反馈!
CREATE Function [dbo].[Covariance](@XmlTwoValueSeries xml)
returns float
as
Begin
/*
-- -----------
-- ALPHA TEST
-- -----------
IF object_id('tempdb..#_201610101706') is not null DROP TABLE #_201610101706
select *
into #_201610101706
from
(
select *
from
(
SELECT '2016-01' Period, 1.24 col0, 2.20 col1
union
SELECT '2016-02' Period, 1.6 col0, 3.20 col1
union
SELECT '2016-03' Period, 1.0 col0, 2.77 col1
union
SELECT '2016-04' Period, 1.9 col0, 2.98 col1
) A
) A
DECLARE @XmlTwoValueSeries xml
SET @XmlTwoValueSeries = (
SELECT col0,col1 FROM #_201610101706
FOR
XML PATH('Output')
)
SELECT dbo.Covariance(@XmlTwoValueSeries) Covariance
*/
declare @returnvalue numeric(20,10)
set @returnvalue =
(
SELECT SUM((x - xAvg) *(y - yAvg)) / MAX(n) AS [COVAR(x,y)]
from
(
SELECT 1E * x x,
AVG(1E * x) OVER (PARTITION BY (SELECT NULL)) xAvg,
1E * y y,
AVG(1E * y) OVER (PARTITION BY (SELECT NULL)) yAvg,
COUNT(*) OVER (PARTITION BY (SELECT NULL)) n
FROM
(
SELECT
e.c.value('(col0/text())[1]', 'float' ) x,
e.c.value('(col1/text())[1]', 'FLOAT' ) y
FROM @XmlTwoValueSeries.nodes('Output') e(c)
) A
) A
)
return @returnvalue
end
GO