Как получить срединные значения при использовании WITH CUBE? - PullRequest
1 голос
/ 09 апреля 2011

В двух словах: при использовании WITH CUBE в MSSQL 2005 существует ли способ прямого вычисления медианных значений, предпочтительно без использования циклов?

Код:

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 и вычислять медиану для каждого набора идентификаторов, но это кажется неэффективным и уродливым.

Любые идеи с благодарностью приняты!

1 Ответ

1 голос
/ 17 июня 2011

С некоторым запозданием я думаю, что это сработает:

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
...