Пример проблемы, упомянутой в моем комментарии к принятому ответу:
select avg(Total) median from
(
select Total,
rnasc = row_number() over(order by Total),
rndesc = row_number() over(order by Total desc)
from [Table]
) b
where rnasc between rndesc - 1 and rndesc + 1
Этот фрагмент не гарантированно сработает, если во входном наборе данных есть повторяющиеся значения - поэтому row_number () не предоставит ожидаемых значений.
Например, для ввода:
DROP TABLE #b
CREATE TABLE #b (id INT IDENTITY, Total INT)
INSERT INTO #b
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 5
UNION ALL SELECT 5 UNION ALL SELECT 5
Внутренний запрос возвращает (я думаю, он может отличаться на разных серверах):
Total rnasc rndesc
5 3 1
5 4 2
5 5 3
1 1 4
1 2 5
Внешний запрос Runnig приведет к NULL (так как нет строки, где rnasc между rndesc - 1 и rndesc + 1 )
Простое решение - добавить некоторый суррогатный ключ (я использовал столбец идентификаторов) в набор данных и включить этот столбец в предложение OVER ():
SELECT avg(Total) median from
(
SELECT Total,
rnasc = row_number() over(order by Total, id),
rndesc = row_number() over(order by Total DESC, id desc)
from #b
) b
WHERE rnasc between rndesc - 1 and rndesc + 1
Теперь порядок сортировки гарантирован, и внутренний запрос возвращает:
Total rnasc rndesc
5 5 1
5 4 2
5 3 3
1 2 4
1 1 5
И результат правильный:)