Oracle
 sql >> डेटाबेस >  >> RDS >> Oracle

Oracle SQL पेयर राइट लेफ्ट सीक्वेंशियल नंबर विद आइडेंटिफायर

यहां एक समाधान है जो अधिक सामान्य रूप से काम करता है, भले ही जोड़े एक-दूसरे के ठीक बगल में न हों। (यदि यह वास्तव में आवश्यक है, यदि भागों को जोड़ा नहीं जा सकता है यदि उनकी आईडी लगातार नहीं है, तो उस शर्त को क्वेरी में जोड़ा जा सकता है।)

with
     test_data ( id, lr, identifier ) as (
       select '001', 'L', 'B15A' from dual union all
       select '002', 'R', 'A15C' from dual union all
       select '003', 'L', 'A15C' from dual union all
       select '004', 'R', 'A15C' from dual union all
       select '005', 'L', 'A15C' from dual union all
       select '006', 'R', 'D5A2' from dual union all
       select '009', 'R', 'D5A2' from dual union all
       select '010', 'L', 'E5A6' from dual union all
       select '011', 'R', 'E5A6' from dual union all
       select '012', 'L', 'E5A6' from dual union all
       select '013', 'R', 'E5A6' from dual union all
       select '014', 'R', 'H9S5' from dual union all
       select '017', 'L', 'EE5A' from dual union all
       select '018', 'R', 'EE5A' from dual
     )
-- end of test data, the solution (SQL query) begins below this line
select id, lr, identifier
from ( select id, lr, identifier,
              row_number() over (partition by identifier, lr order by id) as rn,
              least( count(case when lr = 'L' then 1 end) over (partition by identifier),
                     count(case when lr = 'R' then 1 end) over (partition by identifier)
                   ) as least_count
       from   test_data
)
where rn <= least_count
order by id               --  ORDER BY is optional
;

आउटपुट :

ID  LR IDENTIFIER
--- -- ----------
002 R  A15C
003 L  A15C
004 R  A15C
005 L  A15C
010 L  E5A6
011 R  E5A6
012 L  E5A6
013 R  E5A6
017 L  EE5A
018 R  EE5A

 10 rows selected 

स्पष्टीकरण:आंतरिक क्वेरी में, मैं प्रारंभिक डेटा में दो और कॉलम जोड़ता हूं। एक, rn , प्रत्येक पहचानकर्ता के लिए 'L' और 'R' के लिए अलग-अलग (1 से शुरू होकर 1 से वृद्धि करके) अलग से गिना जाता है। इसका उपयोग जोड़े बनाने के लिए किया जाएगा। और, ct प्रत्येक पहचानकर्ता के लिए 'L' और 'R' के लिए कुल संख्याओं में से कम से कम देता है। बाहरी क्वेरी में, मैं केवल उन सभी पंक्तियों को फ़िल्टर करता हूँ जहाँ rn > ct - वे प्रारंभिक तालिका में एक जोड़ी के बिना पंक्तियाँ हैं। क्या बचा है जोड़े हैं।

जोड़ा गया :अतिरिक्त शर्त के साथ कि एक जोड़ी "लगातार" पंक्तियों से बनाई जानी चाहिए (जैसा कि id द्वारा मापा जाता है) कॉलम), यह एक और दिलचस्प सवाल बन जाता है। यह एक अंतराल और द्वीप समस्या है (एक ही विशेषता के साथ लगातार पंक्तियों के समूहों की पहचान करें), लेकिन एक मोड़ के साथ:LR मूल्य स्थिर होने के बजाय समूह के भीतर वैकल्पिक होना चाहिए। बहुत ही कुशल "टैबिबिटोसन" विधि यहां लागू नहीं की जा सकती (मुझे लगता है); "समूह की शुरुआत" विधि, जो अधिक सामान्य है, काम करती है। यही मैंने यहां इस्तेमाल किया है। ध्यान दें कि अंत में मैं एक समूह में अंतिम पंक्ति को छोड़ देता हूं, यदि समूह की संख्या एक विषम संख्या है। (हमें दो, या चार, या छह लगातार पंक्तियाँ मिल सकती हैं जो एक या दो या तीन जोड़े बनाती हैं, लेकिन वैकल्पिक LR के साथ विषम संख्या में पंक्तियाँ नहीं)। यह भी ध्यान दें कि यदि दो पंक्तियों में एक ही पहचानकर्ता और LR है, तो दूसरी पंक्ति हमेशा एक नया समूह शुरू करेगी, इसलिए यदि यह वास्तव में एक जोड़ी का हिस्सा है (इसके बाद की पंक्ति के साथ), तो इस समाधान द्वारा सही ढंग से पकड़ा जाएगा।

इसकी तुलना Oracle 12 और इसके बाद के संस्करण के लिए MATCH_RECOGNIZE समाधान से करें जिसे मैंने अलग से पोस्ट किया है - और इसकी सराहना करें कि यह कितना सरल है!

with
     prep ( id, lr, identifier, flag ) as (
       select id, lr, identifier,
              case when identifier = lag(identifier) over (order by id) 
                    and lr        != lag(lr)         over (order by id)
                   then null else 1 end
       from test_data    --  replace "test_data" with actual table name
     ), 
     with_groups ( id, lr, identifier, gp ) as (
       select id, lr, identifier,
              sum(flag) over (order by id)
       from   prep
     ),
     with_rn ( id, lr, identifier, rn, ct ) as (
       select id, lr, identifier,
              row_number() over (partition by identifier, gp order by id),
              count(*)     over (partition by identifier, gp)
       from   with_groups
     )
select   id, lr, identifier
from     with_rn
where    rn < ct or mod(rn, 2) = 0
order by id               --  ORDER BY is optional
;


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. संग्रह प्रकार oracle 12c - ORA-00902 से तालिका में सम्मिलित करें:अमान्य डेटाटाइप

  2. ORA-01830:संपूर्ण इनपुट स्ट्रिंग को परिवर्तित करने से पहले दिनांक प्रारूप चित्र समाप्त होता है

  3. समान तालिका की पंक्तियों और स्तंभों की तुलना करें

  4. स्प्रिंग जेडीबीसी में वर्तमान कनेक्शन ऑब्जेक्ट कैसे प्राप्त करें?

  5. SQL त्रुटि ORA 01427