Pergunta

Em primeiro lugar, estou executando em DB2 para i5 / OS V5R4. Eu tenho ROW_NUMBER (), RANK () e expressões de tabela comuns. Eu faço não tem TOP n por cento ou LIMIT OFFSET.

Os dados reais definir Estou trabalhando com é difícil de explicar, então vamos apenas dizer que eu tenho uma tabela de histórico de tempo em que as colunas são (city, temperature, timestamp). Eu quero comparar medianas para médias para cada (city) grupo.

Esta foi a forma mais limpa que eu encontrei para ter uma mediana para uma agregação tabela inteira. Eu adaptei-o da IBM Redbook aqui :

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

Isso funciona bem para obter uma única fileira traseira, mas parece desmoronar para o agrupamento. Conceitualmente, isso é o que eu quero:


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

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

Pode haver uma resposta que me faz parecer estúpido, mas eu estou tendo um bloqueio mental e esta não é minha # 1 coisa a trabalho agora. Parece que poderia ser possível, mas eu não posso usar algo que é extremamente complexa, já que é uma grande mesa e eu quero a capacidade de personalizar as colunas que estão sendo agregadas.

Foi útil?

Solução

No SQL Server, funções agreagate como count (*) pode ser particionado e calculado sem um grupo por. Olhei rapidamente através do redbook referenciada, e parece que DB2 tem a mesma característica. Mas se não, então isso não vai funcionar:

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
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top