Вопрос

Прежде всего, я использую DB2 для i5/OS V5R4.У меня есть ROW_NUMBER(), RANK() и общие табличные выражения.Я делаю нет иметь TOP n PERCENT или LIMIT OFFSET.

Фактический набор данных, с которым я работаю, трудно объяснить, поэтому давайте просто скажем, что у меня есть таблица истории погоды, в которой столбцы (city, temperature, timestamp).Я хочу сравнить медианы со средними значениями для каждой группы. (city).

Это был самый чистый способ получить медианное значение для всей совокупности таблиц.Я адаптировал его из IBM Redbook. здесь:

WITH base_t AS
( SELECT temp, row_number() over (order by temperature) AS rownum FROM t ),
count_t AS
( SELECT COUNT(temperature) + 1 AS base_count FROM base_t ),
median_t AS
( SELECT temperature FROM base_t, count_t
  WHERE rownum in (FLOOR(base_count/2e0), CEILING(base_count/2e0)) )
SELECT DECIMAL(AVG(temperature),10,2) AS median FROM median_t

Это хорошо работает для возврата одной строки, но, похоже, не работает при группировке.Концептуально, это то, что я хочу:


SELECT city, AVG(temperature), MEDIAN(temperature) FROM ...

city           | mean_temp       | median_temp       
===================================================
'Minneapolis'  | 60              | 64
'Milwaukee'    | 65              | 66
'Muskegon'     | 70              | 61

Может быть ответ, который выставит меня глупым, но у меня ментальный блок, и это не моя задача №1, над которой я сейчас работаю.Кажется, что это возможно, но я не могу использовать что-то чрезвычайно сложное, поскольку это большая таблица, и мне нужна возможность настраивать, какие столбцы агрегируются.

Это было полезно?

Решение

В SQL Server агрегатные функции, такие как count(*), можно секционировать и вычислять без группировки.Я быстро просмотрел указанную красную книгу и обнаружил, что DB2 имеет ту же функцию.Но если нет, то это не сработает:

create table TemperatureHistory 
    (City varchar(20)
    , Temperature decimal(5, 2)
    , DateTaken datetime)

insert into TemperatureHistory values ('Minneapolis', 61, '20090101')
insert into TemperatureHistory values ('Minneapolis', 59, '20090102')

insert into TemperatureHistory values ('Milwaukee', 65, '20090101')
insert into TemperatureHistory values ('Milwaukee', 65, '20090102')
insert into TemperatureHistory values ('Milwaukee', 100, '20090103')

insert into TemperatureHistory values ('Muskegon', 80, '20090101')
insert into TemperatureHistory values ('Muskegon', 70, '20090102')
insert into TemperatureHistory values ('Muskegon', 70, '20090103')
insert into TemperatureHistory values ('Muskegon', 20, '20090104')

; with base_t as
    (select city
        , Temperature
        , row_number() over (partition by city order by temperature) as RowNum
        , (count(*) over (partition by city)) + 1 as CountPlusOne 
    from TemperatureHistory)
select City
    , avg(Temperature) as MeanTemp
    , avg(case 
        when RowNum in (FLOOR(CountPlusOne/2.0), CEILING(CountPlusOne/2.0)) 
            then Temperature
            else null end) as MedianTemp
from base_t 
group by City
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top