4
# 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_val1and indx_val2(循环遍历整个表)并返回一个简单的值冠状病毒 ( ABQI, ACNACTR)

4

2 回答 2

4

由于您有在两个不同组上运行的聚合,因此您将需要两个不同的查询。主要的分组依据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

于 2013-08-02T14:35:43.287 回答
0

这是一个标量值函数,用于对格式化为 XML 的任何两列表执行协方差计算。

测试:编译函数然后执行 Alpha 测试

    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
于 2016-10-12T21:14:41.450 回答