एसक्यूएल क्वेरी ओरेकल में कई पंक्तियों से कॉलम मान को समाप्‍त करने के लिए


169

क्या कई पंक्तियों से कॉलम मानों को संक्षिप्त करने के लिए SQL का निर्माण करना संभव होगा?

निम्नलिखित एक उदाहरण है:

तालिका ए

पीआईडी
ए
बी
सी

टेबल बी

PID SEQ डेसक

ए १ है
एक 2 एक अच्छा
एक 3 दिन।
बी 1 अच्छा काम।
सी 1 हां
सी 2 हम कर सकते हैं 
सी 3 करते हैं 
सी 4 इस काम!

SQL का आउटपुट होना चाहिए -

पीआईडी ​​डेसक
आपका दिन मंगलमय हो
B अच्छा काम।
C हां हम यह काम कर सकते हैं!

तो मूल रूप से आउट टेबल के लिए डेस कॉलम टेबल बी से एसईक्यू मानों का एक संयोजन है?

SQL के साथ कोई मदद?


उदाहरण के लिए देखें: halisway.blogspot.com/2006/08/…
Andomar

कृपया इस समाधान को देखें । यह आपके लिए उपयोगी होगा।
जिनेश उंटावीडा

जवाबों:


237

आपके पास किस संस्करण के आधार पर कुछ तरीके हैं - स्ट्रिंग एकत्रीकरण तकनीकों पर ओरेकल प्रलेखन देखें । एक बहुत ही आम का उपयोग करना है LISTAGG:

SELECT pid, LISTAGG(Desc, ' ') WITHIN GROUP (ORDER BY seq) AS description
FROM B GROUP BY pid;

फिर आप चाहते हैं Aलेने के लिए शामिल pidsहों।

नोट: बॉक्स के बाहर, LISTAGGकेवल VARCHAR2कॉलम के साथ सही ढंग से काम करता है ।


2
Oracle 10g के लिए wm_concat () का उपयोग करके पाठ को क्रमांक के आरोही क्रम में कॉमा से सीमांकित किया जाता है, क्या हम कुछ और द्वारा सीमांकित सीमांकित कर सकते हैं?
जगमोट

19

एक XMLAGGफ़ंक्शन भी है, जो 11.2 से पहले के संस्करणों पर काम करता है। क्योंकि WM_CONCATहै undocumented और Oracle द्वारा असमर्थित , यह उत्पादन प्रणाली में उपयोग करने के लिए नहीं की सिफारिश की है।

साथ XMLAGGआप निम्न कर सकते हैं:

SELECT XMLAGG(XMLELEMENT(E,ename||',')).EXTRACT('//text()') "Result" 
FROM employee_names

यह क्या करता है

  • enameस्तंभ के मानों को एक अल्पविराम ( employee_namesतालिका ई के साथ ) में तालिका से अल्पविराम के साथ डालें (टैग ई के साथ)
  • इसका पाठ निकालें
  • xml को एकत्रित करें (इसे संक्षिप्त करें)
  • परिणामी कॉलम "परिणाम" पर कॉल करें

XMLAGG Oracle 12.2 पर काम करता है। इसके अलावा, XLMAGG बहुत लंबे तार को समाप्‍त करने की अनुमति देता है जो LISTAGG अपनी अंतिम लंबाई के कारण नहीं हो सकता है।
मार्को

13

SQL मॉडल क्लॉज के साथ:

SQL> select pid
  2       , ltrim(sentence) sentence
  3    from ( select pid
  4                , seq
  5                , sentence
  6             from b
  7            model
  8                  partition by (pid)
  9                  dimension by (seq)
 10                  measures (descr,cast(null as varchar2(100)) as sentence)
 11                  ( sentence[any] order by seq desc
 12                    = descr[cv()] || ' ' || sentence[cv()+1]
 13                  )
 14         )
 15   where seq = 1
 16  /

P SENTENCE
- ---------------------------------------------------------------------------
A Have a nice day
B Nice Work.
C Yes we can do this work!

3 rows selected.

मैंने यहाँ इस बारे में लिखा था । और यदि आप ओटीएन-थ्रेड के लिंक का पालन करते हैं, तो आपको प्रदर्शन तुलना सहित कुछ और मिलेंगे।


10

LISTAGG विश्लेषणात्मक समारोह में पेश किया गया था ओरेकल 11g रिलीज़ 2 , कुल तार करने के लिए बहुत आसान है यह बना रही है। यदि आप 11 जी रिलीज़ 2 का उपयोग कर रहे हैं, तो आपको स्ट्रिंग एकत्रीकरण के लिए इस फ़ंक्शन का उपयोग करना चाहिए। स्ट्रिंग संघनन के बारे में अधिक जानकारी के लिए कृपया url नीचे देखें।

http://www.oracle-base.com/articles/misc/StringAggregationTechniques.php

स्ट्रिंग कॉनटेनटेशन


8

जैसा कि अधिकांश उत्तर सुझाते हैं, LISTAGGस्पष्ट विकल्प है। हालाँकि, इसके साथ एक कष्टप्रद पहलू LISTAGGयह है कि यदि समतल स्ट्रिंग की कुल लंबाई 4000 वर्ण ( VARCHAR2एसक्यूएल में सीमा ) से अधिक है, तो नीचे दी गई त्रुटि को फेंक दिया गया है, जो 12.1 तक के Oracle संस्करणों में प्रबंधित करना मुश्किल है

ORA-01489: स्ट्रिंग संघनन का परिणाम बहुत लंबा है

12cR2 में जोड़ा गया एक नया फीचर ON OVERFLOWहै LISTAGG। इस खंड सहित क्वेरी इस तरह दिखाई देगी:

SELECT pid, LISTAGG(Desc, ' ' on overflow truncate) WITHIN GROUP (ORDER BY seq) AS desc
FROM B GROUP BY pid;

उपरोक्त आउटपुट को 4000 वर्णों तक सीमित कर देगा, लेकिन ORA-01489त्रुटि नहीं करेगा ।

ये ON OVERFLOWखंड के कुछ अतिरिक्त विकल्प हैं :

  • ON OVERFLOW TRUNCATE 'Contd..' : यह 'Contd..'स्ट्रिंग के अंत में प्रदर्शित होगा (डिफ़ॉल्ट है ...)
  • ON OVERFLOW TRUNCATE '' : यह बिना किसी समाप्ति स्ट्रिंग के 4000 वर्णों को प्रदर्शित करेगा।
  • ON OVERFLOW TRUNCATE WITH COUNT: यह समाप्ति वर्णों के बाद वर्णों की कुल संख्या प्रदर्शित करेगा। जैसे: - ' ...(5512)'
  • ON OVERFLOW ERROR: यदि आप त्रुटि के LISTAGGसाथ विफल होने की उम्मीद करते हैं ORA-01489(जो वैसे भी डिफ़ॉल्ट है)।

6

उन लोगों के लिए जिन्हें Oracle 9i (या पहले) का उपयोग करके इस समस्या को हल करना होगा, आपको शायद SYS_CONNECT_BY_PATH का उपयोग करना होगा, क्योंकि LISTAGG उपलब्ध नहीं है।

ओपी का जवाब देने के लिए, निम्नलिखित प्रश्न तालिका A से PID प्रदर्शित करेगा और तालिका B से सभी DESC कॉलमों को मिलाएगा:

SELECT pid, SUBSTR (MAX (SYS_CONNECT_BY_PATH (description, ', ')), 3) all_descriptions
FROM (
       SELECT ROW_NUMBER () OVER (PARTITION BY pid ORDER BY pid, seq) rnum, pid, description
       FROM (
              SELECT a.pid, seq, description
              FROM table_a a, table_b b
              WHERE a.pid = b.pid(+)
             )
      )
START WITH rnum = 1
CONNECT BY PRIOR rnum = rnum - 1 AND PRIOR pid = pid
GROUP BY pid
ORDER BY pid;

ऐसे उदाहरण भी हो सकते हैं जहाँ कुंजियाँ और मान सभी एक ही तालिका में समाहित हैं। निम्न क्वेरी का उपयोग किया जा सकता है जहां कोई तालिका A नहीं है, और केवल तालिका B मौजूद है:

SELECT pid, SUBSTR (MAX (SYS_CONNECT_BY_PATH (description, ', ')), 3) all_descriptions
FROM (
       SELECT ROW_NUMBER () OVER (PARTITION BY pid ORDER BY pid, seq) rnum, pid, description
       FROM (
              SELECT pid, seq, description
              FROM table_b
             )
      )
START WITH rnum = 1
CONNECT BY PRIOR rnum = rnum - 1 AND PRIOR pid = pid
GROUP BY pid
ORDER BY pid;

सभी मूल्यों को वांछित के रूप में फिर से व्यवस्थित किया जा सकता है। व्यक्तिगत संक्षिप्त विवरण को विभाजन द्वारा खंड में फिर से व्यवस्थित किया जा सकता है, और PID की सूची को अंतिम ORDER BY खंड में पुन: व्यवस्थित किया जा सकता है।


वैकल्पिक रूप से: ऐसे समय हो सकते हैं जब आप पूरी तालिका से सभी मानों को एक पंक्ति में जोड़ना चाहते हैं।

यहाँ महत्वपूर्ण विचार, विवरण के समूह के लिए कृत्रिम मूल्य का उपयोग कर रहा है।

निम्नलिखित प्रश्न में, निरंतर स्ट्रिंग '1' का उपयोग किया जाता है, लेकिन कोई भी मूल्य काम करेगा:

SELECT SUBSTR (MAX (SYS_CONNECT_BY_PATH (description, ', ')), 3) all_descriptions
FROM (
       SELECT ROW_NUMBER () OVER (PARTITION BY unique_id ORDER BY pid, seq) rnum, description
       FROM (
              SELECT '1' unique_id, b.pid, b.seq, b.description
              FROM table_b b
             )
      )
START WITH rnum = 1
CONNECT BY PRIOR rnum = rnum - 1;

अलग-अलग संक्षिप्त विवरण को खंड द्वारा खंड में पुन: व्यवस्थित किया जा सकता है।

इस पृष्ठ पर कई अन्य उत्तरों ने भी इस अत्यंत उपयोगी संदर्भ का उल्लेख किया है: https://oracle-base.com/articles/misc/string-aggregation-techniques


3
  1. LISTAGG सबसे अच्छा प्रदर्शन देता है यदि छँटाई करना आवश्यक है (00: 00: 05.85)

    SELECT pid, LISTAGG(Desc, ' ') WITHIN GROUP (ORDER BY seq) AS description FROM B GROUP BY pid;

  2. अगर छँटाई की आवश्यकता नहीं है तो COLLECT सबसे अच्छा प्रदर्शन देता है (00: 00: 02.90):

    SELECT pid, TO_STRING(CAST(COLLECT(Desc) AS varchar2_ntt)) AS Vals FROM B GROUP BY pid;

  3. आदेश देने के साथ थोड़ा धीमा है (00: 00: 07.08):

    SELECT pid, TO_STRING(CAST(COLLECT(Desc ORDER BY Desc) AS varchar2_ntt)) AS Vals FROM B GROUP BY pid;

अन्य सभी तकनीकें धीमी थीं।


1
आपके उत्तर के बारे में विस्तार से बताना उपयोगी होगा।
जॉन सुरेल

जॉन, l लेख से दोहराना नहीं चाहते थे, लेकिन संक्षेप में ये परिणाम हैं: 1. LISTAGG सबसे अच्छा प्रदर्शन बचाता है अगर छँटाई करना आवश्यक है (00: 00: 05.85) 2. COLLECT सबसे अच्छा प्रदर्शन देता है अगर छँटाई नहीं है जरूरत (००: ००: ०२.९ ०): सेलेक्ट पीआईडी, TO_STRING (CAST (COLLECT (ASC)) varchar2_ntt के रूप में) AS Vals from B GROUP by pid; 3. ऑर्डर करने के साथ COLLECT थोड़ा धीमा है (00: 00: 07.08): Select pid, TO_STRING (CAST (COLLECT (DESD ORDER BY Desc)) AS varchar2_ntt) के रूप में) P से B ग्रुप से; अन्य सभी तकनीकें धीमी थीं।
मीशो

1
आप प्रासंगिक जानकारी को शामिल करने के लिए बस अपने उत्तर को संपादित कर सकते हैं।
जॉन सरेल

मुझे संपादन में बहुत देर हो गई और इसीलिए मैंने इसे फिर से जोड़ा। क्षमा करें, मैं यहां नया हूं और बस इसे लटकाना शुरू कर रहा हूं।
मिशो

1

चयन क्वेरी चलाने से पहले, इसे चलाएं:

SET SERVEROUT ON SIZE 6000

SELECT XMLAGG(XMLELEMENT(E,SUPLR_SUPLR_ID||',')).EXTRACT('//text()') "SUPPLIER" 
FROM SUPPLIERS;


-3

चयन में जहाँ आप अपना संघटन चाहते हैं, SQL फ़ंक्शन को कॉल करें।

उदाहरण के लिए:

select PID, dbo.MyConcat(PID)
   from TableA;

फिर SQL फ़ंक्शन के लिए:

Function MyConcat(@PID varchar(10))
returns varchar(1000)
as
begin

declare @x varchar(1000);

select @x = isnull(@x +',', @x, @x +',') + Desc
  from TableB
    where PID = @PID;

return @x;

end

फ़ंक्शन हेडर सिंटैक्स गलत हो सकता है, लेकिन सिद्धांत काम करता है।


यह Oracle के लिए अमान्य है
a_horse_with_no_name
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.