Pregunta

En primer lugar, estoy corriendo en DB2 para i5 / OS V5R4. Tengo ROW_NUMBER (), RANK () y expresiones de tabla comunes. Hago no tienen TOP n por ciento o LÍMITE offset.

El conjunto de datos reales que estoy trabajando es difícil de explicar, así que vamos a decir que tengo una tabla de historial de tiempo donde las columnas son (city, temperature, timestamp). Quiero comparar las medianas de promedios para cada grupo (city).

Esta era la manera más limpia que he encontrado para conseguir un medio para un agregación de toda la tabla. Lo adapté del Redbook de IBM aquí :

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

Esto funciona bien para conseguir una única fila de atrás, pero parece desmoronarse para la agrupación. Conceptualmente, esto es lo que quiero:


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

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

Puede haber una respuesta que me hace parecer estúpido, pero estoy teniendo un bloqueo mental y esto no es lo mío # 1 para trabajar en este momento. Parece que podría ser posible, pero no puedo usar algo que es extremadamente complejo, ya que es una mesa grande y quiero la posibilidad de personalizar las columnas que están siendo agregadas.

¿Fue útil?

Solución

En SQL Server, funciones agreagate como count (*) puede ser dividido y calcula sin un grupo por. Miré rápidamente a través del libro rojo de referencia, y parece que DB2 tiene la misma característica. Pero si no es así, entonces esto no va a 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 bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top