2009-08-07 7 views
0

Als Erstes verwende ich DB2 für i5/OS V5R4. Ich habe ROW_NUMBER(), RANK() und allgemeine Tabellenausdrücke. Ich habe nicht haben TOP n PERCENT oder LIMIT OFFSET.DB2 SQL - Median mit GROUP BY

Der eigentliche Datensatz, mit dem ich arbeite, ist schwer zu erklären, also lassen Sie uns einfach sagen, dass ich eine Wetterhistorientabelle habe, in der die Spalten (city, temperature, timestamp) sind. Ich möchte für jede Gruppe Mediane mit Durchschnittswerten vergleichen (city).

Dies war der sauberste Weg, den ich gefunden habe, um einen Median für eine ganze Tabellenaggregation zu erhalten. Ich passte es von der 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 

, dass eine einzige Zeile für immer wieder gut funktioniert, aber es scheint für die Gruppierung auseinander zu fallen. Konzeptionell ist das, was ich will:


SELECT city, AVG(temperature), MEDIAN(temperature) FROM ... 
 
city   | mean_temp  | median_temp  
=================================================== 
'Minneapolis' | 60    | 64 
'Milwaukee' | 65    | 66 
'Muskegon'  | 70    | 61 

Es könnte eine Antwort sein, die mich dumm aussehen lässt, aber ich habe eine mentale Blockade und das ist nicht meine # 1, was im Augenblick zu arbeiten. Scheint so, als könnte es möglich sein, aber ich kann nicht etwas verwenden, das extrem komplex ist, da es eine große Tabelle ist und ich die Möglichkeit haben möchte, welche Spalten aggregiert werden.

Antwort

1

In SQL Server können agreagate-Funktionen wie count (*) ohne eine Gruppe partitioniert und berechnet werden. Ich blätterte schnell durch das referenzierte Redbook und es sieht so aus, als hätte DB2 die gleiche Funktion. Aber wenn nicht, dann wird dies nicht funktionieren:

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

Ich werde dies versuchen, ich muss wirklich besser zu verstehen, OLAP. Vielen Dank. – twblamer

+0

Ich stelle dies als die akzeptierte Antwort ein. Es funktioniert mit der Anzahl (*) in DB2 LUW 9.5, aber leider nicht in DB2 für i. Da niemand sonst irgendwelche Ideen hatte, werde ich mit dieser Einschränkung leben müssen. Danke noch einmal. – twblamer