1

一言で言えば、MSSQL2005でWITHCUBEを使用する場合、できればループを使用せずに中央値を直接計算する方法はありますか?

いくつかのコード:

CREATE TABLE #Example (
    ID1 INT,
    ID2 INT,
    [Value] INT
)

INSERT #Example(ID1,ID2,[Value])
    SELECT 1, 1, 45 UNION
    SELECT 1, 2, 78 UNION
    SELECT 1, 3, 23 UNION
    SELECT 1, 4, 119 UNION
    SELECT 1, 5, 85 UNION
    SELECT 2, 1, 143 UNION
    SELECT 2, 2, 124 UNION
    SELECT 2, 3, 161 UNION
    SELECT 2, 4, 171 UNION
    SELECT 2, 5, 142

SELECT ID1, ID2, COUNT(1) AS 'NumValues', MIN([Value]) AS 'Minimum', AVG([Value]) AS 'Average', MAX([Value]) AS 'Maximum'
    FROM #Example
    GROUP BY ID1, ID2
    WITH CUBE
    HAVING ID1 IS NULL OR ID2 IS NULL
    ORDER BY ISNULL(ID1, 0), ISNULL(ID2, 0)

DROP TABLE #Example

中央値の列を取得するにはどうすればよいですか?

私がこれまでに管理した最善の方法は、ID1とID2の値をループし、IDの各セットの中央値を計算することですが、これは非効率的で醜いようです。

どんなアイデアもありがたく受けました!

4

1 に答える 1

1

やや遅れて、これはうまくいくと思います:

select * from
(
    SELECT ID1, ID2, COUNT(1) AS 'NumValues', MIN([Value]) AS 'Minimum', AVG([Value]) AS 'Average', MAX([Value]) AS 'Maximum'
    FROM #Example
    GROUP BY ID1, ID2
    WITH CUBE
    HAVING ID1 IS NULL OR ID2 IS NULL
) T
OUTER APPLY 
(
    select avg(val) as median from
    (
        select [value] as val, row_number() over (order by [value]) as rn
        from #Example E 
        where (T.ID1=E.ID1 or T.ID1 is null) and (T.ID2=E.ID2 or T.ID2 is null) 
    ) I
    where abs(rn - (T.NumValues+1)/2.0) <1
) T2
于 2011-06-17T12:16:38.707 に答える