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_val1(indx_val2テーブル全体をループ)、単純な値を返すcov( ABQI, ACNACTR)

4

2 に答える 2

4

2 つの異なるグループに対して集計を実行しているため、2 つの異なるクエリが必要になります。dt主なものは、日付ごとに行の値を取得するためにグループ化します。他のクエリは、行セット全体AVG()で実行およびCOUNT()集計する必要があります。

両方を同時に使用するには、JOIN一緒に使用する必要があります。しかし、2 つのクエリ間に実際の関係がないため、これはデカルト積であり、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 にフォーマットされた任意の 2 列テーブルで共分散計算を実行するスカラー値関数です。

テストするには: 関数をコンパイルして、アルファ テストを実行します。

    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 に答える