سؤال

أولا، أنا أعمل على DB2 لـ i5/OS V5R4.لدي ROW_NUMBER() وRANK() وتعبيرات الجدول الشائعة.أفعل لا لديك TOP n PERCENT أو LIMIT OFFSET.

من الصعب شرح مجموعة البيانات الفعلية التي أعمل بها، لذا دعنا نقول فقط أن لدي جدول تاريخ الطقس حيث توجد الأعمدة (city, temperature, timestamp).أريد مقارنة المتوسطات بالمتوسطات لكل مجموعة (city).

كانت هذه هي الطريقة الأنظف التي وجدتها للحصول على متوسط ​​لتجميع الجدول بأكمله.لقد قمت بتكييفه من 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

يعمل هذا بشكل جيد لاستعادة صف واحد، ولكن يبدو أنه ينهار عند التجميع.من الناحية النظرية، هذا ما أريد:


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

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

من الممكن أن تكون هناك إجابة تجعلني أبدو غبيًا، لكن لدي كتلة عقلية وهذا ليس الشيء رقم 1 الذي يجب أن أعمل عليه الآن.يبدو أن ذلك ممكن، لكن لا يمكنني استخدام شيء معقد للغاية نظرًا لأنه جدول كبير وأريد القدرة على تخصيص الأعمدة التي يتم تجميعها.

هل كانت مفيدة؟

المحلول

في SQL Server، يمكن تقسيم الوظائف المجمعة مثل count(*) وحسابها بدون مجموعة.لقد بحثت سريعًا في الكتاب الأحمر المشار إليه، ويبدو أن DB2 لديه نفس الميزة.ولكن إذا لم يكن الأمر كذلك، فلن ينجح هذا:

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
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top