2011-03-17 15 views
0

我有兩個具有一對多關係的表。單個SQL使用列中的分隔符選擇一對多關係表 - Oracle

表人:

Id_person Name 
----------------------- 
1   Jack Black 
2   Joe White 

表電話:

Id_telephone Id_person Number  Type 
---------------------------------------- 
5   1   333222111 Mobile 
6   1   444333222 Fax 
7   2   555444333 Mobile 

SQL SELECT語句的期望的結果:

Name  Telephone_Numbers 
--------------------------------------------- 
Jack Black Mobile: 333222111, Fax: 444333222 
Joe White Mobile: 555444333 

我發現有很多回答這個問題,而是關係到SQL服務器,我不知道如何使用Oracle數據庫10g完成此任務。我需要使用這個結果填充ASP.NET中的Gridview,所以我想將這個SELECT語句與OracleCommand和ExecuteQuery()一起使用。

感謝您的任何提示。

回答

2

在11gR2中,你可以使用listAgg

with person as 
(
select 1 id_person, 'Jack Black' FullName from dual 
union all 
select 2 id_person, 'Joe White' FullName from dual 
) 
, telephone as 
(
select 5 id_telephone ,   1 Id_person,  333222111 phone_Number , 'Mobile' phone_type from dual 
union all 
select 6 id_telephone ,   1 Id_person,  444333222 phone_Number , 'Fax' phone_type from dual 
union all 
select 7 id_telephone ,   2 Id_person,  555444333 phone_Number , 'Mobile' phone_type from dual 
) 
select person.FullName 
     ,listagg(telephone.phone_type || ': ' || telephone.phone_number , ', ') within group (order by person.FullName) personToPhone 

    from person 
     inner join 
     telephone 
     on person.id_person = telephone.id_person 
group by person.FullName ; 


FULLNAME PERSONTOPHONE                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
---------- ----------------------------------- 
Jack Black Fax: 444333222, Mobile: 333222111                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 
Joe White Mobile: 555444333 

看這個問題的其他解決辦法, comma-separated list as a result of select statement in Oracle

編輯

的10G您可以使用XMLAGG

with person as 
(
select 1 id_person, 'Jack Black' FullName from dual 
union all 
select 2 id_person, 'Joe White' FullName from dual 
) 
, telephone as 
(
select 5 id_telephone ,   1 Id_person,  333222111 phone_Number , 'Mobile' phone_type from dual 
union all 
select 6 id_telephone ,   1 Id_person,  444333222 phone_Number , 'Fax' phone_type from dual 
union all 
select 7 id_telephone ,   2 Id_person,  555444333 phone_Number , 'Mobile' phone_type from dual 
) 
select person.FullName 
    ,RTRIM(XMLAGG(XMLELEMENT(e,telephone.phone_type || ': ' || telephone.phone_number || ',')).EXTRACT('//text()'),',') AS TelephoneToType 
    from person 
     inner join 
     telephone 
     on person.id_person = telephone.id_person 
group by person.FullName ; 

FULLNAME TELEPHONETOTYPE                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
---------- --------------------------------- 
Jack Black Mobile: 333222111,Fax: 444333222                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 
Joe White Mobile: 555444333 

(馬克·貝克在鏈接的SO問題所做的那樣)

+0

什麼約10克? – sanjuro 2011-03-17 19:36:27

+0

@sanjuro在 – Harrison 2011-03-17 19:47:29

1
Select P.Name 
    , 'Mobile: ' || Coalesce(Min(Case When T.Type = 'Mobile' Then Number End),'') 
     + Coalesce('Fax: ' || Min(Case When T.Type = 'Fax' Then Number End),'') 
From Person P 
    Join Telephone T 
     On T.Id_Person = P.Id_person 
Group By P.Name 
+0

以上添加了一個不同的方法謝謝我會嘗試 – sanjuro 2011-03-17 19:41:25

1

有可能的解決方案here

+0

感謝您的鏈接,我會看看它 – sanjuro 2011-03-17 19:40:49

0

這應該爲你工作的列表。如果您使用的是11g,則有一個內置的聚合函數LISTAGG,它更容易:

with data 
as 
( 
    select 
     p.id_person, 
     p.name, 
     t.type||': '||t.phone_number telephone_number, 
     row_number() over (partition by p.id_person order by t.type) rn, 
     count(*) over (partition by p.id_person) cnt 
    from 
     person p 
     inner join telephone t 
      on t.id_person = p.id_person 
) 
select 
    name, 
    ltrim(sys_connect_by_path(telephone_number,', '),', ') telephone_number 
from data 
where rn = cnt 
start with rn = 1 
connect by prior id_person = id_person and prior rn = rn-1 
order by id_person 
1

回到頂端時有同樣的問題。我發現所有答案都使用listagg,但客戶端使用10g。創建此功能。函數不是我在網上找到的。

create or replace 
FUNCTION column_concat 
(
    p_cursor sys_refcursor, 
    p_del VARCHAR2 
) RETURN VARCHAR2 
IS 
    l_value VARCHAR2(32767); 
    l_result VARCHAR2(32767); 
BEGIN 
    LOOP 
     FETCH p_cursor INTO l_value; 
     EXIT WHEN p_cursor%notfound; 
     IF l_result IS NOT NULL THEN 
     l_result := l_result || p_del; 
    END IF; 
    l_result := l_result || l_value; 
END LOOP; 
RETURN l_result; 
END column_concat; 

使用它選擇像這樣:

select pers.name Names, column_concat(cursor(SELECT tel.type ||':' || tel.telnumber FROM person per, telephone tel Where per.id_person = tel.id_person and tel.id_person = pers.id_person), ',') Telephone_Numbers from person pers;