2010-11-11 16 views
5

मैं ओरेकल पीएल/एसक्यूएल का उपयोग कर रहा हूं।पीएल/एसक्यूएल में, आप अगली पंक्ति के आधार पर पंक्ति कैसे अपडेट करते हैं?

मैं एक टाइमस्टैंप तालिका टी है, और मुझे पिछली पंक्ति के समान होने के लिए स्तंभ एक के लिए एक पंक्ति का मूल्य निर्धारित करना चाहते हैं, अगर वे कॉलम बी और समय-चिह्न के अनुसार क्रमबद्ध रहे हैं, बशर्ते कि टाइम स्टांप नहीं हैं 45 सेकंड से अधिक अलग।

UPDATE T t_curr 
    SET A = 
    (SELECT A 
     FROM T t_prev 
     INNER JOIN t_curr 
     ON (t_prev is the row right before t_curr, when you sort by B and Timestamp) 
      AND t_curr.Timestamp - t_prev.Timestamp < 45 
    ) 

मैं इस कोशिश की:

UPDATE T t_curr 
    SET A = 
    (SELECT A 
     FROM T t_prev 
     INNER JOIN t_curr 
     ON RANK (t_curr) 
      OVER (B, Timestamp) 
      = 1 + RANK (t_prev) 
      OVER (B, Timestmap) 
      AND t_curr.Timestamp - t_prev.Timestamp < 45 
    ) 

लेकिन मुझे मिल गया:

स्यूडोकोड में, यह कुछ की तरह है

त्रुटि (38,16): PL/SQL: ओआरए -00 9 34: समूह समारोह की अनुमति नहीं है

रैंक के पहले उदाहरण पर इशारा करते हुए।

मैंने क्या गलत किया, और मैं यह अधिकार कैसे प्राप्त करूं?

+1

के बारे में मैं 'का उपयोग कर lag' या' lead' सुझाव देने के लिए था, लेकिन है कि या तो काम कर सकते हैं नहीं है ... या आप की कोशिश कर सकते 'अद्यतन टी से एक = Q1.A चयन सेट ((चयन टी से एक, ROWNUM आर 1) Q1 Q1.r1 = Q2.r2-1) ' – FrustratedWithFormsDesigner

+0

@FrustratedWithFormsDesigner पर बाहरी छोड़ दिया में शामिल होने के (ए का चयन करें, टी से ROWNUM r2) Q2 - आप सही है कि अंतराल कर रहे हैं और मुझे एक ही समस्या मिल ले जाते हैं। मुझे संकलन करने के लिए आपके अन्य सुझावों के आधार पर कुछ मिला, हालांकि, धन्यवाद! अगर आप इसे स्वीकार करने के लिए इसे जवाब में कॉपी करना चाहते हैं, तो यह ठीक होगा। –

+0

हो गया! (मैं क्योंकि मैं एक अद्यतन के लिए यह करने की कोशिश की और यह सुनिश्चित करें कि यह काम करेगा नहीं था कभी नहीं किया है पहली बार में टिप्पणी के रूप में तैनात);) – FrustratedWithFormsDesigner

उत्तर

3

मर्ज स्टेटमेंट का उपयोग करने का प्रयास करें। यकीन नहीं है कि यह वही करता है जो आप चाहते हैं लेकिन इसे काम करना चाहिए। दुर्भाग्यवश सम्मिलित खंड आवश्यक है) लेकिन इसे कभी भी नहीं बुलाया जाना चाहिए।

merge into t a 
using (
    select 
    A, 
    B, 
    timestamp, 
    lag(A) over (order by id, timestamp) as prior_A, 
    lag(timestamp) over (order by B, timestamp) as prior_timestamp 
    from t) b 
on (a.B = b.B) 
when matched then 
    update set a.a = case when b.timestamp-b.prior_timestamp <= 45 
    then b.prior_A else b.A end 
when not matched then insert (B) values (null) 
+0

धन्यवाद! मुझे संकलन करने के लिए कुछ मिल गया है, और यह मुझे समझ में आता है कि इसे काम करना चाहिए। –

+1

मुझे अभी भी लगता है कि आपको देखने की आवश्यकता हो सकती है आपकी आवश्यकताओं। क्या होता है जब आपके पास एक-दूसरे के 45 सेकंड के भीतर कई लेन-देन होते हैं? उदाहरण के लिए, सभी पंक्तियों में 40 सेकंड अलग हैं? –

1

आप कुछ इस तरह की कोशिश कर सकते हैं:

update x 
set x = y.A 
from T x 
join T y 
where x.B = (select MAX(B) from T where B < y.B) 
and x.Timestamp = (select MAX(Timestamp) from T where Timestamp < y.Timestamp) 
and y.Timestamp - x.Timestamp < 45 
+0

मुझे लगता है कि ऐसा महसूस प्रदर्शन की समस्याओं का कारण होता है, ऐसा नहीं है? मैं हजारों पंक्तियों से निपट रहा हूं। –

+1

@ MOE37x3 मैं कुछ भी नहीं मानूंगा ... आप किसके साथ बात करते हैं, इस पर निर्भर करता है कि हजारों पंक्तियों में वास्तव में इतना कुछ नहीं है। – Fosco

0

आप की कोशिश कर सकते हैं (कुछ फेरबदल की आवश्यकता हो सकती यह सही पाने के लिए, लेकिन यह विचार दो समान आदेश दिया rownumbers ऑफसेट से जुड़े हुए सबक्वेरी है)

update T set a = (select A1 
       from (
         select S1.A A1, rownum r1 
         from (select * from T order by B, timestamp) S1 
         left outer join 
         select S2.A A2, rownum r2 
         from (select * from T order by B, timestamp) S2 
         on r1 = r2-1 
        ) 
       ) 
+0

ऐसा लगता है कि राउनम खाते में आदेश नहीं लेता है। यह सिर्फ पंक्तियों तक पहुंचने के क्रम में करता है। http://www.dbforums.com/oracle/988716-rownum-order.html –

+0

@ MOE37x3: मुझे पता है, मेरे पहले व्यक्ति के पास कोई ऑर्डर नहीं था। मैं बी और टाइमस्टैम्प क्षेत्र पर addded आदेश। क्या ये तुम्हारे लिए कारगर है? – FrustratedWithFormsDesigner

+0

जो मैंने पढ़ा है उसके अनुसार, राउनम ऑर्डर से पहले लागू हो जाता है, इसलिए संख्याएं वहां होंगी, और पंक्तियां निर्दिष्ट क्रम में होंगी, लेकिन संख्याएं किसी अन्य क्रम में हो सकती हैं। –

1

और एक और विकल्प ... काफी है क्योंकि यह आवश्यकता पर ध्यान नहीं देता बी पर सॉर्ट करने के लिए, लेकिन यह आप कुछ के बारे में सोचना दे सकता है .... तालिका परिभाषा और बातें यह था के बिना क्या चाहते हो ऐसा नहीं करता है वास्तव में क्या आवश्यक था पर एक संभाल पाने के लिए थोड़ा मुश्किल है।

संपादित करें: फिर से प्रश्न पढ़ने पर, ऐसा लगता है कि आपका वाक्यविन्यास गलत है। समूह कार्य (लीड/अंतराल/रैंक इत्यादि) केवल चयनित सूची या खंड द्वारा क्रम में दिखाई दे सकते हैं। जुड़ने के बाद उनका मूल्यांकन किया जाता है, जहां समूह द्वारा क्लॉज किया जाता है। तो नीचे दिखाए गए कुछ की तरह काम करना चाहिए।

update T a 
set A = (select 
    new_A 
    from (
    select 
    B, 
    A, 
    timestamp, 
    first_value(A) 
     over (order by timestamp range between 45 preceding and current row) as new_A 
    from mike_temp_1 
) b where b.id = a.id) 
+0

मेरे कोड में त्रुटि की व्याख्या करने के लिए धन्यवाद। –

0

आप क्या कर सकते है।

update t 
set colToUpdate = nextValue 
from (
select A 
     ,B 
     ,C 
     ,(LEAD(B, 1, null) over (order by A)) as nextValue 
    FROM db.schema.table 
) as t 
    where colToUpdate is null 

यह आवश्यक है कि आप जिस कॉलम को अपडेट करना चाहते हैं वह शून्य है, जब तक कि आप उन सभी को अपडेट नहीं करना चाहते।

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