使用SQL查找协方差

使用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()聚合 要同

我有一个表,看起来像^(但有数百行,日期从2009年到2013年)。是否有一种方法可以计算协方差:[(
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