2009-08-07 6 views
0

Tout d'abord, je suis sous DB2 pour i5/OS V5R4. J'ai ROW_NUMBER(), RANK() et des expressions de table communes. Je fais pas avoir TOP n pour cent ou LIMIT OFFSET. L'ensemble de données avec lequel je travaille est difficile à expliquer, alors disons simplement que j'ai un tableau d'historique météorologique où les colonnes sont (city, temperature, timestamp). Je veux comparer les médianes aux moyennes pour chaque groupe (city).DB2 SQL - médiane avec GROUP BY

C'était la manière la plus propre que j'ai trouvée pour obtenir une médiane pour une agrégation de table entière. J'adaptèrent de l'IBM Redbook here:

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. , C'est 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 c'est possible, mais je ne peux pas utiliser quelque chose d'extrêmement complexe car c'est une grande table et je veux pouvoir personnaliser les colonnes qui sont agrégées.

Répondre

1

Dans SQL Server, les fonctions agreagate telles que count (*) peuvent être partitionnées et calculées sans groupe. J'ai regardé rapidement à travers le redbook référencé, et il semble que DB2 a la même fonctionnalité. 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 
+0

Je vais essayer, j'ai vraiment besoin de mieux comprendre OLAP. Merci. – twblamer

+0

Je définis ceci comme réponse acceptée. Cela fonctionne avec le compte (*) dans DB2 LUW 9.5, mais malheureusement pas dans DB2 pour i. Puisque personne d'autre n'a eu d'idées, je suppose que je vais devoir vivre avec cette limitation. Merci encore. – twblamer