كيف يمكن الجمع بين عدة صفوف في قائمة بفواصل في أوراكل ؟ [مكررة]

StackOverflow https://stackoverflow.com/questions/468990

سؤال

هذا السؤال سبق الجواب هنا:

لدي استفسار بسيط:

select * from countries

النتائج التالية:

country_name
------------
Albania
Andorra
Antigua
.....

أود أن أعود النتائج في صف واحد ، لذلك مثل هذا:

Albania, Andorra, Antigua, ...

بالطبع أستطيع أن أكتب PL/SQL وظيفة للقيام بهذه المهمة (لقد فعلت في Oracle 10g) ، ولكن هل هناك أجمل ، ويفضل أن يكون غير أوراكل-حل معين (أو قد تكون المدمج في وظيفة) لهذه المهمة ؟

أنا عموما استخدامه لتجنب صفوف متعددة في الاستعلامات ، حتى إذا كان الشخص لديه أكثر من جنسية واحدة ، وأنا لا أريد له أن يكون نسخة مكررة في القائمة.

سؤالي هو بناء على مثل هذا السؤال على SQL server 2005.

التحديث:بلدي وظيفة تبدو مثل هذا:

CREATE OR REPLACE FUNCTION APPEND_FIELD (sqlstr in varchar2, sep in varchar2 ) return varchar2 is
ret varchar2(4000) := '';
TYPE cur_typ IS REF CURSOR;
rec cur_typ;
field varchar2(4000);
begin
     OPEN rec FOR sqlstr;
     LOOP
         FETCH rec INTO field;
         EXIT WHEN rec%NOTFOUND;
         ret := ret || field || sep;
     END LOOP;
     if length(ret) = 0 then
          RETURN '';
     else
          RETURN substr(ret,1,length(ret)-length(sep));
     end if;
end;
هل كانت مفيدة؟

المحلول

هنا هو طريقة بسيطة دون stragg أو إيجاد وظيفة.

create table countries ( country_name varchar2 (100));

insert into countries values ('Albania');

insert into countries values ('Andorra');

insert into countries values ('Antigua');


SELECT SUBSTR (SYS_CONNECT_BY_PATH (country_name , ','), 2) csv
      FROM (SELECT country_name , ROW_NUMBER () OVER (ORDER BY country_name ) rn,
                   COUNT (*) OVER () cnt
              FROM countries)
     WHERE rn = cnt
START WITH rn = 1
CONNECT BY rn = PRIOR rn + 1;

CSV                                                                             
--------------------------
Albania,Andorra,Antigua                                                         

1 row selected.

كما ذكر آخرون, إذا كنت على 11g R2 أو أكثر ، يمكنك الآن استخدام listagg الذي هو أبسط من ذلك بكثير.

select listagg(country_name,', ') within group(order by country_name) csv
  from countries;

CSV                                                                             
--------------------------
Albania, Andorra, Antigua

1 row selected.

نصائح أخرى

على WM_CONCAT وظيفة (إذا المدرجة في قاعدة البيانات الخاصة بك قبل أوراكل 11.2) أو LISTAGG (ابتداء من أوراكل 11.2) ينبغي أن تفعل خدعة بشكل جيد.على سبيل المثال, هذا يحصل بفواصل قائمة أسماء الجداول في المخطط:

select listagg(table_name, ', ') within group (order by table_name) 
  from user_tables;

أو

select wm_concat(table_name) 
  from user_tables;

مزيد من التفاصيل/الخيارات

رابط الوثائق

Oracle يمكنك استخدام LISTAGG

يمكنك استخدام هذا أيضا:

SELECT RTRIM (
          XMLAGG (XMLELEMENT (e, country_name || ',')).EXTRACT ('//text()'),
          ',')
          country_name
  FROM countries;

يمكنك أن تجرب هذا الاستعلام.

select listagg(country_name,',') within group (order by country_name) cnt 
from countries; 

أسرع طريقة هو استخدام أوراكل جمع وظيفة.

يمكنك أيضا القيام بذلك:

select *
  2    from (
  3  select deptno,
  4         case when row_number() over (partition by deptno order by ename)=1
  5             then stragg(ename) over
  6                  (partition by deptno
  7                       order by ename
  8                         rows between unbounded preceding
  9                                  and unbounded following)
 10         end enames
 11    from emp
 12         )
 13   where enames is not null

زيارة موقع نسأل توم و البحث في 'stragg" أو "سلسلة سلسلة' .الكثير من أمثلة.وهناك أيضا ليست موثقة أوراكل وظيفة لتحقيق الاحتياجات الخاصة بك.

أنا في حاجة إلى شيء مماثل وجدت الحل التالي.

select RTRIM(XMLAGG(XMLELEMENT(e,country_name || ',')).EXTRACT('//text()'),',') country_name from  

في هذا المثال نقوم بإنشاء دالة تجلب فاصلة تحدد قائمة متميزة مستوى خط AP الفاتورة عقد الأسباب في حقل واحد على رأس المستوى الاستعلام:

 FUNCTION getHoldReasonsByInvoiceId (p_InvoiceId IN NUMBER) RETURN VARCHAR2

  IS

  v_HoldReasons   VARCHAR2 (1000);

  v_Count         NUMBER := 0;

  CURSOR v_HoldsCusror (p2_InvoiceId IN NUMBER)
   IS
     SELECT DISTINCT hold_reason
       FROM ap.AP_HOLDS_ALL APH
      WHERE status_flag NOT IN ('R') AND invoice_id = p2_InvoiceId;
BEGIN

  v_HoldReasons := ' ';

  FOR rHR IN v_HoldsCusror (p_InvoiceId)
  LOOP
     v_Count := v_COunt + 1;

     IF (v_Count = 1)
     THEN
        v_HoldReasons := rHR.hold_reason;
     ELSE
        v_HoldReasons := v_HoldReasons || ', ' || rHR.hold_reason;
     END IF;
  END LOOP;

  RETURN v_HoldReasons;
END; 

لقد كان دائما لكتابة بعض PL/SQL لهذا أو أنا فقط لسلسلة ',' الميدان و نسخ إلى محرر إزالة الكروم من قائمة يعطيني سطر واحد.

وهذا هو ،

select country_name||', ' country from countries

قليلا طويلة ينضب في كلا الاتجاهين.

إذا نظرتم نسأل توم سوف ترى الكثير من الحلول الممكنة ولكن كلها تعود إلى نوع الإعلانات و/أو PL/SQL

نسأل توم

SELECT REPLACE(REPLACE
((SELECT     TOP (100) PERCENT country_name + ', ' AS CountryName
FROM         country_name
ORDER BY country_name FOR XML PATH('')), 
'&<CountryName>', ''), '&<CountryName>', '') AS CountryNames

يمكنك استخدام هذا الاستعلام للقيام أعلاه المهمة

DECLARE @test NVARCHAR(max)
SELECT @test = COALESCE(@test + ',', '') + field2 FROM #test SELECT field2= @test

لمزيد من التفاصيل خطوة بخطوة شرح زيارة الرابط التالي
http://oops-solution.blogspot.com/2011/11/sql-server-convert-table-column-data.html

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top