计算表中各列之间的相关性

时间:2018-10-23 13:02:57

标签: sql-server

我正在尝试创建一个存储过程,该存储过程用于计算临时表中某些列之间的相关性。

我有一个查询,该查询会生成一个如下所示的临时表,

 Date         USA     JAPAN    FRANCE   UK 
 2018-01-01   5       3.2      1.6      2.8
 2018-01-02   6.8     8.2      0.9      3.5
 2018-01-03   4.3     6.2      3.3      2.1
 2018-01-04   3.9     6.2      4.5      7.8
 ...
 2018-01-31   7.6     5.1      4.7      5.1

我想计算所有列之间的相关性。下面的查询正是这样做的。

SELECT 
(Avg(SeriesA * SeriesB) - (Avg(SeriesA) * Avg(SeriesB))) / (StDevP(SeriesA) * StDevP(SeriesB))  
FROM myTempTbl

但是我的临时表中的列数可能会发生变化,即可能添加或删除了另一个国家等

计算所有列之间的相关性以输出如下所示结果的最佳方法是什么?

我想要的结果如下所示(已建立相关性)

    Country1  Country2   Correlation
    USA       JAPAN      0.1
    USA       FRANCE     0.1
    USA       UK         0.1
    JAPAN     FRANCE     0.1
    JAPAN     UK         0.1
    FRANCE    UK         0.1

2 个答案:

答案 0 :(得分:2)

我怀疑这是您的追求,但是,我得到的结果与您的不匹配(我得到的值0代表每一行的相关性),这可能是因为您的样本数据意味着更多的数据(您尚未提供,因此问题中的预期结果并不代表所提供的样本数据)。但是,这至少应该将您推向正确的方向:

CREATE TABLE CountryData (DataDate date,
                          Country varchar(15),
                          SomeDecimal decimal(2,1)); --No idea what this represents

WITH VTE AS(
    SELECT *
    FROM (VALUES('20180101',5  ,3.2,1.6,2.8),
                ('20180102',6.8,8.2,0.9,3.5),
                ('20180103',4.3,6.2,3.3,2.1),
                ('20180104',3.9,6.2,4.5,7.8),
                ('20180131',7.6,5.1,4.7,5.1)) V([Date],USA,JAPAN,FRANCE,UK))
--Pivot the data. This is not dynamic, I am simply showing you what you need to data to look like.
--It was far quicker for me to take your existing data and pivot it, than transcribe it all in Normal Form
INSERT INTO CountryData
SELECT V.[Date],
       C.Country,
       CASE C.Country WHEN 'USA' THEN USA
                      WHEN 'JAPAN' THEN JAPAN
                      WHEN 'FRANCE' THEN FRANCE
                      WHEN 'UK' THEN UK
       END AS SomeDecimal
FROM VTE V
     CROSS APPLY (VALUES('USA'),('JAPAN'),('FRANCE'),('UK')) C(Country);
GO
--How your data should look
SELECT *
FROM CountryData;
GO
--And now the (much simpler) non-dynamic solution
SELECT CDa.Country AS Country1,
       CDb.Country As Country2,
       (Avg(CDa.SomeDecimal * CDb.SomeDecimal) - (Avg(CDa.SomeDecimal) * Avg(CDb.SomeDecimal))) / (StDevP(CDa.SomeDecimal) * StDevP(CDb.SomeDecimal)) AS Correlation
FROM CountryData CDa
     JOIN CountryData CDb ON CDa.Country != CDb.Country
GROUP BY CDa.Country, CDb.Country
ORDER BY CDa.Country, CDb.Country;

GO
DROP TABLE CountryData;

答案 1 :(得分:0)

选择(Avg(x * y)–(Avg(x)* Avg(y)))/(StDevP(x)* StDevP(y))作“关联”