2012-11-05 13 views
5

परिभाषित करने के लिए मैं इस तालिका है:औसत विभाजन

create table t (value int, dt date); 

value |  dt  
-------+------------ 
    10 | 2012-10-30 
    15 | 2012-10-29 
    null | 2012-10-28 
    null | 2012-10-27 
    7 | 2012-10-26 

और मैं इस उत्पादन हैं:

value |  dt  
-------+------------ 
    10 | 2012-10-30 
    5 | 2012-10-29 
    5 | 2012-10-28 
    5 | 2012-10-27 
    7 | 2012-10-26 

मैं शून्य मान चाहते है, साथ ही एक पिछले गैर शून्य मान, जब तालिका को अवरोही से आदेश दिया जाता है तो पिछले शून्य के औसत से प्रतिस्थापित किया जाना चाहिए। इस उदाहरण में मान 15 पिछले दो नल के पिछले शून्य मूल्य नहीं है। तो 15/3 = 5.

SQL Fiddle

+0

+1 बहुत अच्छा सवाल है। और इसमें सब कुछ है जो इसकी ज़रूरत है - ठीक है, मैं पहेली से PostgreSQL 9.2 का अनुमान लगाता हूं। –

उत्तर

4

मैं एक आश्चर्यजनक रूप से सरल समाधान नहीं मिला:

SELECT max(value) OVER (PARTITION BY grp) 
    /count(*) OVER (PARTITION BY grp) AS value 
     ,dt 
FROM (
    SELECT *, count(value) OVER (ORDER BY dt DESC) AS grp 
    FROM t 
    ) a; 

-> sqlfiddle

count() के बाद से NULL मूल्यों पर ध्यान नहीं देता है, तो आप मौजूदा संख्या (खिड़की समारोह में डिफ़ॉल्ट) का उपयोग कर सकते समूह मूल्यों को जल्दी से (->grp)।

प्रत्येक समूह में वास्तव में एक गैर-शून्य मान है, इसलिए हम उसी के परिणामस्वरूप एक और विंडो फ़ंक्शन में उसी परिणाम प्राप्त करने के लिए न्यूनतम/अधिकतम/योग का उपयोग कर सकते हैं। grp में NULL मानों की गणना करने के लिए सदस्यों की संख्या (count(*) इस समय विभाजित करें!) और हम कर चुके हैं।

+0

अच्छा, लेकिन PostgreSQL-विशिष्ट लगता है। – jsalvata

+0

@jsalvata: "लेकिन"? क्या आपने [PostgreSQL] टैग देखा था? इसके अलावा, यह मानक एसक्यूएल है। [-> ** समान क्वेरी के साथ SQL सर्वर ** के लिए sqlfiddle] (http://www.sqlfiddle.com/#!6/fb11e/1)। –

+1

नहीं, मैंने नहीं किया। क्रैपी mySQL इसका समर्थन नहीं करता है। हाँ, यह मानक है। – jsalvata

1

एक पहेली के रूप में, इस अभ्यास में यह बुरी तरह अपने डेटा की प्रकृति पर निर्भर प्रदर्शन कर सकते हैं एक समाधान है ...। अपने अनुक्रमित देखो, किसी भी मामले में:

create database tmp; 
create table t (value float, dt date); -- if you use int, you need to care about rounding 
insert into t values (10, '2012-10-30'), (15, '2012-10-29'), (null, '2012-10-28'), (null, '2012-10-27'), (7, '2012-10-26'); 

select t1.dt, t1.value, t2.dt, t2.value, count(*) cnt 
from t t1, t t2, t t3 
where 
    t2.dt >= t1.dt and t2.value is not null 
    and not exists (
     select * 
     from t 
     where t.dt < t2.dt and t.dt >= t1.dt and t.value is not null 
    ) 
    and t3.dt <= t2.dt 
    and not exists (
     select * 
     from t where t.dt >= t3.dt and t.dt < t2.dt and t.value is not null 
    ) 
group by t1.dt; 

+------------+-------+------------+-------+-----+ 
| dt   | value | dt   | value | cnt | 
+------------+-------+------------+-------+-----+ 
| 2012-10-26 |  7 | 2012-10-26 |  7 | 1 | 
| 2012-10-27 | NULL | 2012-10-29 | 15 | 3 | 
| 2012-10-28 | NULL | 2012-10-29 | 15 | 3 | 
| 2012-10-29 | 15 | 2012-10-29 | 15 | 3 | 
| 2012-10-30 | 10 | 2012-10-30 | 10 | 1 | 
+------------+-------+------------+-------+-----+ 
5 rows in set (0.00 sec) 

select dt, value/cnt 
from (
    select t1.dt , t2.value, count(*) cnt 
    from t t1, t t2, t t3 
    where 
     t2.dt >= t1.dt and t2.value is not null 
     and not exists (
      select * 
      from t 
      where t.dt < t2.dt and t.dt >= t1.dt and t.value is not null 
     ) 
    and t3.dt <= t2.dt 
    and not exists (
     select * 
     from t 
     where t.dt >= t3.dt and t.dt < t2.dt and t.value is not null 
    ) 
    group by t1.dt 
) x; 

+------------+-----------+ 
| dt   | value/cnt | 
+------------+-----------+ 
| 2012-10-26 |   7 | 
| 2012-10-27 |   5 | 
| 2012-10-28 |   5 | 
| 2012-10-29 |   5 | 
| 2012-10-30 |  10 | 
+------------+-----------+ 
5 rows in set (0.00 sec) 

स्पष्टीकरण:

  • t1 मूल तालिका है
  • t2 एक गैर शून्य मान
  • साथ कम से कम अधिक से अधिक की तारीख के साथ तालिका में पंक्ति है
  • t3 के बीच में सभी पंक्तियों हैं, इसलिए हम दूसरों के द्वारा समूह और भरोसा कर सकते हैं

खेद है कि मैं स्पष्ट नहीं हो सकता। यह मेरे लिए बहुत भ्रामक :-)

+0

यदि यह समझाने के लिए बहुत जटिल है, संभावना है, यह बहुत जटिल है। :) –

+0

दरअसल। Clodoaldo के संपादन के बाद लगभग समझ में आता है। – jsalvata

संबंधित मुद्दे