Question

Tout d'abord, je suis en cours d'exécution sur DB2 pour i5 / OS V5R4. Je ROW_NUMBER (), RANK () et les expressions de table commune. Je fais pas TOP ont n pour cent ou LIMIT OFFSET.

L'ensemble de données réelles, je travaille avec est difficile à expliquer, alors disons simplement que j'ai une table d'historique de temps où les colonnes sont (city, temperature, timestamp). Je veux comparer aux moyennes valeurs médianes pour chaque (city) du groupe.

C'était la manière la plus propre que j'ai trouvé pour obtenir une médiane pour une agrégation de table entière. J'adaptèrent du 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

Cela fonctionne bien pour obtenir une seule rangée arrière, mais il semble se désagréger pour le regroupement. Conceptuellement, ce que je veux:


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

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

Il pourrait y avoir une réponse qui me fait l'air stupide, mais je vais avoir un bloc mental et ce n'est pas mon # 1 chose à travailler en ce moment. On dirait que cela pourrait être possible, mais je ne peux pas utiliser quelque chose qui est extrêmement complexe car il est une grande table et je veux la possibilité de personnaliser les colonnes sont regroupées.

Était-ce utile?

La solution

Dans SQL Server, les fonctions agreagate comme count (*) peut être partitionné et calculé sans groupe par. J'ai regardé rapidement à travers le Redbook référencé, et il semble que DB2 a la même fonction. Mais sinon, cela ne fonctionnera pas:

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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top