2011-01-13 13 views
104

में एकाधिक पंक्तियों से कॉलम मानों को समेकित करने के लिए SQL क्वेरी एकाधिक पंक्तियों से कॉलम मानों को संयोजित करने के लिए एसक्यूएल बनाना संभव होगा?ओरेकल

तालिका A

 
PID 
A 
B 
C 

टेबल बी एसक्यूएल की

 
PID SEQ Desc 

A  1  Have 
A  2  a nice 
A  3  day. 
B  1  Nice Work. 
C  1  Yes 
C  2  we can 
C  3  do 
C  4  this work! 

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

 
PID Desc 
A  Have a nice day. 
B  Nice Work. 
C  Yes we can do this work! 

तो मूल रूप से वर्णन:

निम्नलिखित एक उदाहरण है बाहर के लिए कॉलम टेबल टेबल से एसईक्यू मानों का एक सारणी है?

एसक्यूएल के साथ कोई मदद?

+0

उदाहरण के लिए देखें: http://halisway.blogspot.com/2006/08/oracle-groupconcat-updated-again.html – Andomar

+0

कृपया [इस समाधान] देखो (https://stackoverflow.com/a/19348687/2459039)। यह आपके लिए उपयोगी होगा। ओरेकल 10 जी के लिए wm_concat() का उपयोग करके –

उत्तर

156

आपके पास कौन सा संस्करण है इसके आधार पर कुछ तरीके हैं - oracle documentation on string aggregation techniques देखें। एक बहुत ही आम एक LISTAGG उपयोग करने के लिए है:

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

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

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

+2

कॉमा द्वारा सीमित अनुक्रम संख्या के आरोही क्रम में पाठ को जोड़ता है, क्या हम किसी और चीज़ से सीमित उतर सकते हैं? – jagamot

-3

या ओरेकल STRAGG (कॉलम) फ़ंक्शन।

मुझे कहना है, प्रसंस्करण यह बहुत ही सीमित ... यदि आप क्षेत्र चौड़ाई या प्रदर्शन चौड़ाई से अधिक इस तरह की ...

10
एसक्यूएल मॉडल खंड के साथ

:

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. 

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

4

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

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

String Concatenation

14

वहाँ भी है एक XMLAGG समारोह है, जो 11.2 से पहले के संस्करणों पर काम करता है। क्योंकि WM_CONCATundocumented and unsupported by Oracle है, यह अनुशंसा की जाती है कि इसे उत्पादन प्रणाली में उपयोग न करें।

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

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

क्या करता

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

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

SET SERVEROUT ON SIZE 6000

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

इस कोड का प्रयास करें:

SELECT XMLAGG(XMLELEMENT(E,fieldname||',')).EXTRACT('//text()') "FieldNames" 
    FROM FIELD_MASTER 
    WHERE FIELD_ID > 10 AND FIELD_AREA != 'NEBRASKA'; 
0

LISTAGG का उपयोग सबसे व्यावहारिक है और यह सर्वोत्तम प्रदर्शन प्रदान करता है ई अपवाद, ऑर्डर करने की आवश्यकता नहीं है। यहां अधिक जानकारी: http://www.oracle-developer.net/display.php?id=515

+1

आपके उत्तर को विस्तारित करना उपयोगी होगा। –

+0

जॉन, मैं लेख से दोहराना नहीं चाहता था, लेकिन संक्षेप में ये परिणाम हैं: 1. सॉर्टिंग एक जरूरी है (LI: 00: 05.85) 2. संग्रह सबसे अच्छा प्रदर्शन प्रदान करता है अगर सॉर्टिंग की आवश्यकता नहीं है (00: 00: 02.90): सिलेक्ट पिड, TO_STRING (CAST (COLLECT (Desc) AS varchar2_ntt)) एएस वैल्स बी ग्रुप द्वारा ग्रुप; 3. आदेश के साथ इकट्ठा थोड़ा धीमा (: 00: 07.08 00): है चयन पीआईडी, TO_STRING (कास्ट (इकट्ठा varchar2_ntt के रूप में वर्णन द्वारा (वर्णन आदेश))) Vals के रूप में बी से पीआईडी ​​द्वारा ग्रुप; अन्य सभी तकनीकें धीमी थीं। – Misho

+1

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

-2

उस चयन में जहां आप अपनी समाप्ति चाहते हैं, एक SQL फ़ंक्शन कॉल करें।

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

select PID, dbo.MyConcat(PID) 
    from TableA; 
फिर एसक्यूएल समारोह के लिए

:

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 

समारोह हैडर वाक्य रचना गलत हो सकता है, लेकिन सिद्धांत काम करता है।

+0

यह ओरेकल के लिए अमान्य है –

1

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

ओपी उत्तर देने के लिए, निम्न क्वेरी तालिका A से पीआईडी ​​को प्रदर्शित करने और टेबल बी से सभी 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 निम्न क्वेरी इस्तेमाल किया जा सकता है, और केवल तालिका बी मौजूद है: के रूप में वांछित

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; 

सभी मान पुनर्क्रमित जा सकता है। व्यक्तिगत समेकित विवरण को खंड द्वारा भाग में पुन: व्यवस्थित किया जा सकता है, और पीआईडी ​​की सूची अंतिम ORDER द्वारा खंड में पुन: व्यवस्थित की जा सकती है।


वैकल्पिक: कई बार जब आप एक पंक्ति में एक संपूर्ण तालिका से सभी मूल्यों को श्रेणीबद्ध करने के लिए चाहते हो सकता है।

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

निम्न क्वेरी, निरंतर स्ट्रिंग '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; 

व्यक्तिगत श्रेणीबद्ध विवरण BY खंड विभाजन में पुनर्क्रमित जा सकता है। https://oracle-base.com/articles/misc/string-aggregation-techniques

0

मैं LISTAGG का उपयोग कर, लेकिन फारसी स्ट्रिंग के लिए इस स्ट्रिंग लौटाने:

इस पृष्ठ पर कई अन्य सवालों के जवाब भी इस अत्यंत उपयोगी संदर्भ का उल्लेख किया है!

मेरी क्वेरी:

SELECT 
listagg(DESCRIPTION,' , ') within group (order by DESCRIPTION) 
FROM 
B_CEREMONY 

परिणाम:

'A7'1 , ,4F 

कृपया मेरी मदद करो।

वाह इस समाधान काम किया जाता है:

SELECT listagg(convert(DESCRIPTION, 'UTF8', 'AL16UTF16'),' , ') within group 
(order by DESCRIPTION) 
FROM B_CEREMONY; 
0

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

ORA ओरेकल संस्करणों में प्रबंधन करने के लिए मुश्किल है -01,489: स्ट्रिंग संयोजन का परिणाम बहुत लंबा

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

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

ऊपर 4000 अक्षरों तक उत्पादन को प्रतिबंधित करेगा लेकिन ORA-01489 त्रुटि फेंक नहीं होंगे।

  • ON OVERFLOW TRUNCATE 'Contd..':

    ये ON OVERFLOW खंड के अतिरिक्त विकल्प में से कुछ हैं यह में स्ट्रिंग के अंत (डिफ़ॉल्ट ... है)

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

11g और उच्च: उपयोग listagg:

SELECT 
    col1, 
    LISTAGG(col2, ', ') WITHIN GROUP (ORDER BY col2) "names" 
FROM table_x 
GROUP BY col1 

10 ग्राम और कम:

CREATE OR REPLACE FUNCTION get_comma_separated_value (input_val in number) 
    RETURN VARCHAR2 
IS 
    return_text VARCHAR2(10000) := NULL; 
BEGIN 
    FOR x IN (SELECT col2 FROM table_name WHERE col1 = input_val) LOOP 
    return_text := return_text || ',' || x.col2 ; 
    END LOOP; 
    RETURN LTRIM(return_text, ','); 
END; 
/

समारोह का उपयोग करने के लिए:: एक विधि एक समारोह का उपयोग करने के लिए है

select col1, get_comma_separated_value(col1) from table_name 

नोट: ओरेकल के कुछ पुराने संस्करणों पर उपलब्ध एक (असमर्थित) फ़ंक्शन WM_CONCAT है, जो आपकी मदद कर सकता है - here for details देखें।

MySQL में:

SELECT col1, GROUP_CONCAT(col2) FROM table_name GROUP BY col1