# 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
我有一个看起来像 ^ 的表(但有数百行,日期从 2009 年到 2013 年)。有没有办法计算协方差: [(indx_val1
- avg(indx_val1
)) * (indx_val2
- avg( indx_val2
)] 除以 indx_val1
和 indx_val2
的每个值的总行数(循环遍历整个表)并仅返回 cov( ABQI
、ACNACTR
)
最佳答案
由于您的聚合在两个不同的组上运行,因此您将需要两个不同的查询。主要的一个按 dt
分组以获取每个日期的行值。另一个查询必须在整个行集中执行 AVG()
和 COUNT()
聚合。
要同时使用它们,您需要将它们JOIN
在一起。但由于两个查询之间没有实际关系,因此它是笛卡尔积,我们将使用CROSS JOIN
。实际上,它将主查询的每一行与聚合查询检索到的单行连接起来。然后,您可以使用两者中的值在 SELECT
列表中执行算术运算:
因此,基于您之前问题的查询:
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
这是一个基于您之前的演示的演示:http://sqlfiddle.com/#!6/2ec65/14
关于sql - 使用 SQL 求协方差,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18019469/