2011-12-02 13 views
6

मैं ओरेकल विश्लेषणात्मक कार्यों के साथ काफी अनुभवी हूं लेकिन इसने मुझे रोक दिया है। हो, तो एक स्पष्ट समाधान :)दिलचस्प ओरेकल विश्लेषणात्मक क्वेरी चुनौती

मैं एक मेज, जर्नल, जो आवेषण, अद्यतन रिकॉर्ड और एक अन्य मेज पर हटाता है मैं अपने आप को लात हूँ।

तालिका जो यह एक पत्रिका है BOND_PAYMENTS है, जो भुगतान और बांड के बीच संबंधों का प्रतिनिधित्व करती है; यह किसी विशेष भुगतान (PAYMENT_ID द्वारा पहचाना गया) से किसी विशेष बांड (BOND_NUMBER द्वारा पहचाना गया) को आवंटित धनराशि (AMOUNT) संग्रहीत करता है। इसके अलावा, यह रिकॉर्ड करता है कि बॉन्ड का कौन सा पहलू आवंटित किया गया था (BOP_DOMAIN) जो 'बॉन', 'पीईटी' या कुछ अन्य कोड हो सकता है। BOND_PAYMENTS तालिका में एक सरोगेट कुंजी (BOP_ID) है।

इसलिए, मेरी पत्रिका तालिका आमतौर पर प्रत्येक BOP_ID के लिए 1 या अधिक रिकॉर्ड होगा - सबसे पहले, एक सम्मिलित है, शायद कुछ अपडेट के बाद, एक को हटाने के द्वारा शायद पीछा किया।

INSERT INTO JOURNAL VALUES (TO_DATE('01/01/2010','DD/MM/YYYY'),'INS',1242043,1003700,'9995/10','BON',1800); 
INSERT INTO JOURNAL VALUES (TO_DATE('03/01/2010','DD/MM/YYYY'),'INS',1242046,1003700,'9998/10','BON',1700); 
INSERT INTO JOURNAL VALUES (TO_DATE('04/01/2010','DD/MM/YYYY'),'INS',1242048,1003700,'9999/10','BON',1800); 
INSERT INTO JOURNAL VALUES (TO_DATE('05/01/2010','DD/MM/YYYY'),'INS',1242052,1003700,'10003/10','BON',1600); 
INSERT INTO JOURNAL VALUES (TO_DATE('08/01/2010','DD/MM/YYYY'),'INS',1242058,1003700,'9998/10','BON',100); 
INSERT INTO JOURNAL VALUES (TO_DATE('09/01/2010','DD/MM/YYYY'),'UPD',1242058,1003700,'9998/10','PET',100); 
INSERT INTO JOURNAL VALUES (TO_DATE('01/01/2010','DD/MM/YYYY'),'INS',2242043,1003701,'8995/10','BON',1800); 
INSERT INTO JOURNAL VALUES (TO_DATE('02/01/2010','DD/MM/YYYY'),'INS',2242046,1003701,'8998/10','BON',1700); 
INSERT INTO JOURNAL VALUES (TO_DATE('03/01/2010','DD/MM/YYYY'),'INS',2242048,1003701,'8999/10','BON',1800); 
INSERT INTO JOURNAL VALUES (TO_DATE('04/01/2010','DD/MM/YYYY'),'INS',2242058,1003701,'8998/10','BON',100); 
INSERT INTO JOURNAL VALUES (TO_DATE('05/01/2010','DD/MM/YYYY'),'UPD',2242046,1003701,'8998/10','BON',1500); 
INSERT INTO JOURNAL VALUES (TO_DATE('06/01/2010','DD/MM/YYYY'),'INS',2242052,1003701,'9003/10','BON',1600); 
INSERT INTO JOURNAL VALUES (TO_DATE('07/01/2010','DD/MM/YYYY'),'UPD',2242058,1003701,'8998/10','PET',200); 

अब, मैं इस पत्रिका मेज से लेकिन एक अलग में डेटा का एक पूरा सेट को निकालने के लिए की जरूरत है:

CREATE TABLE JOURNAL 
(JN_DATE_TIME DATE   NOT NULL, 
    JN_OPERATION VARCHAR2(3) NOT NULL, 
    BOP_ID  NUMBER(9) NOT NULL, 
    PAYMENT_ID NUMBER(9) NOT NULL, 
    BOND_NUMBER VARCHAR2(20) NOT NULL, 
    BOP_DOMAIN VARCHAR2(10) NOT NULL, 
    AMOUNT  NUMBER(14,2) NOT NULL 
); 

यहां कुछ नमूना डेटा है:

यहाँ पत्रिका तालिका है प्रारूप। मुख्य आवश्यकता यह है कि हम नहीं चाहते कि जर्नल टेबल अब BOP_DOMAIN रिकॉर्ड करे - इसकी आवश्यकता नहीं है।

मुझे प्रत्येक BOND_PAYMENT रिकॉर्ड के लिए कुल राशि का इतिहास उत्पन्न करने की आवश्यकता है। मैं BOND_PAYMENT तालिका का उपयोग नहीं कर सकता क्योंकि यह केवल प्रत्येक रिकॉर्ड की नवीनतम स्थिति दिखाता है। मुझे जर्नल से यह जानकारी खनन करने की ज़रूरत है।

मैं सिर्फ एक SUM(amount) over(partition by payment_id, bond_number) नहीं ले सकते क्योंकि एक व्यक्ति BOP_ID कई बार अद्यतन किया जा सकता है; तो समय में किसी एक पल में केवल उस BOP_ID के लिए रिकॉर्ड की गई नवीनतम राशि का उपयोग किया जाना चाहिए।

SELECT jn_date_time, 
     jn_operation, 
     bop_id, 
     payment_id, 
     bond_number, 
     bop_domain, 
     amount, 
     ? as running_total 
FROM JOURNAL 
ORDER BY jn_date_time; 

sample data and expected results

यहाँ मैं छोड़ दिया नमूना डेटा पर पुनः प्रस्तुत किया है, दो नमूना भुगतान के लिए:

ऊपर नमूना डेटा को देखते हुए, यहाँ एक उदाहरण है कि मैं क्या निर्माण करने के लिए उम्मीद थी है । दाईं ओर मुझे "रनिंग टोटल" मिला है, जो अपेक्षित आउटपुट है। इसके आगे (लाल रंग में) यह तर्क है कि यह प्रत्येक पंक्ति के लिए चल रहे कुल की गणना कैसे करता है।

"चल रहा कुल" एक स्नैपशॉट जर्नल प्रविष्टि के समय में बिंदु पर,, PAYMENT_ID और BOND_NUMBER की कि संयोजन के लिए कुल राशि का है। याद रखें, एक विशेष BOP_ID कई बार अपडेट किया जा सकता है; कुल राशि को उस BOP_ID के लिए केवल हालिया रिकॉर्ड पर विचार करना चाहिए।

किसी भी समाधान है कि काम करता है स्वीकार्य होगा, लेकिन मैं एक विश्लेषणात्मक समारोह (या विश्लेषणात्मक कार्यों के संयोजन) संदेह है कि यह हल करने के लिए सबसे अच्छा तरीका हो जाएगा।

उत्तर

6

इस

WITH inner AS 
    (SELECT jn_date_time, 
    jn_operation, 
    bop_id, 
    payment_id, 
    bond_number, 
    bop_domain, 
    amount, 
    amount - coalesce(lag(amount) over (partition by bop_id order by jn_date_time), 0)  
     as delta_bop_amount 
    FROM JOURNAL) 
SELECT inner.*, 
sum(delta_bop_amount) 
    over (partition by payment_id, bond_number order by jn_date_time) as running_total 
FROM inner 
ORDER BY bond_number, payment_id 

यह आपके उदाहरण के लिए एक ही जवाब वापस आ जाएगी की कोशिश करो।

आपको दो पास की आवश्यकता है - आंतरिक क्वेरी में विश्लेषणात्मक कार्य यह बताता है कि प्रत्येक रिकॉर्ड प्रत्येक BOP_ID के लिए कुल कितना बदलता है।एक आईएनएस एक सीधा जोड़ है, एक यूपीडी को सबसे हालिया मूल्य घटाना है और नया जोड़ना है।

दूसरा पास फिर बॉन्ड/भुगतान द्वारा कुल रनिंग करता है।

मुझे लगता है कि आप बॉन्ड/भुगतान को चल रहे योग के लिए प्राकृतिक कुंजी के रूप में देखना चाहते हैं, और यह कि किसी भी बॉन्ड/भुगतान संयोजन के लिए कई BOP_ID हो सकते हैं।

+0

बहुत अच्छा :) मैं देखता हूं कि आप वहां क्या कर रहे हैं। आप पहली बार गणना करते हैं कि पिछली प्रासंगिक प्रविष्टि (एलएजी के माध्यम से) से कितनी राशि बदली गई है, तो यह केवल डेल्टा में चल रहे योग की गणना करने की बात है। –

+0

आपकी धारणाएं सही हैं। –

0
SELECT a.*, 
lag(amount,1) over (PARTITION BY bond_number ORDER BY 
payment_id,jn_date_time)recent_amount, 
amount + nvl(lag(amount,1) over (PARTITION BY bond_number ORDER BY 
payment_id,jn_date_time),0) running_total 
FROM JOURNAL a 
ORDER BY payment_id,jn_date_time 

यह समाधान सटीक उत्तर प्रदान करता है जिसे आप उपर्युक्त प्रश्न के लिए उम्मीद कर रहे हैं और वह भी एक टेबल पास में :)।

मैंने प्रति बॉन्ड_नंबर/पेमेंट_आईडी संयोजन की राशि का सबसे हालिया मूल्य प्राप्त करने के लिए अभी एक अंतराल विश्लेषणात्मक फ़ंक्शन का उपयोग किया है और फिर जोड़ा गया है कि कुल राशि प्राप्त करने के लिए राशि की हालिया राशि मान ... सरल !!! .. संकेत यह :)

+0

अच्छा प्रयास करें, लेकिन यह बॉन्ड 9998/10 के लिए bop_id = 1242058 के लिए $ 200 की गलत रिपोर्ट करता है - इसे $ 1800 दिखाना चाहिए। कारण यह है कि आपका रनिंग कुल भुगतान_आईडी/जेएन_डेट_टाइम द्वारा क्रमबद्ध पिछली पंक्ति से राशि जोड़ रहा है, जबकि इसे इतिहास में उस भुगतान के लिए सभी परिवर्तनों पर विचार करने की आवश्यकता है। @ Wrschneider के उत्तर पर एक नज़र डालें जो सही परिणाम देता है। –

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