2010-11-10 7 views
7

Ho scritto una soluzione al problema usando PL/SQL e SQL e non posso fare a meno di pensare che potrebbe essere fatto al 100% in SQL, ma sto facendo fatica ad iniziare.Soluzione al problema in PL/SQL come apparire in SQL?

Qui è la struttura delle due tabelle (Se aiuta, gli script per creare loro sono alla fine della questione)

tabella T1 (chiave primaria è entrambe le colonne visualizzate)

ID TYPE 
1  A 
1  B 
1  C 

2  A 
2  B 

3  B 

la colonna Tipo è una chiave esterna tabella T2, che contiene i seguenti dati:

tabella T2 (chiave primaria è Type)

Type Desc 
A  xx 

B  xx 

C  xx 

Quindi, dato l'i dati nel T1 il risultato ho bisogno saranno:

Per ID 1 perché ha tutti i tipi nella tabella chiave esterna sarei tornato il letterale "All"

Per ID 2 perché ha due tipi Vorrei tornare "a & B" (notare il separatore)

E infine per ID 3, perché ha un tipo mi piacerebbe tornare solo "B"

Come promesso qui sono gli script per creare tutti gli oggetti menzionati.

create table t2(type varchar2(1), 
       description varchar2(100) 
       )     
/

insert into t2 
values ('A', 'xx') 
/

insert into t2 
values ('B', 'xx') 
/

insert into t2 
values ('C', 'xx') 
/

alter table t2 add constraint t2_pk primary key (type) 
/

create table t1 (id number(10), 
       type varchar2(1) 
       ) 
/

alter table t1 add constraint t1_pk primary key(id, type) 
/

alter table t1 add constraint t1_fk foreign key (type) 
references t2(type) 
/

insert into t1 
values (1, 'A') 
/

insert into t1 
values (1, 'B') 
/

insert into t1 
values (1, 'C') 
/

insert into t1 
values (2, 'A') 
/

insert into t1 
values (2, 'B') 
/

insert into t1 
values (3, 'B') 
/
+0

Hai intenzione di aggiungere altri tipi in t2? Non solo A, B e C? – mcpeterson

+0

@mcpeterson: Grazie per il commento. I dati in t2 verranno corretti, con un totale di circa 5 righe –

+1

La necessità di concatenazione di stringhe orientate al gruppo nega la possibilità di farlo in puro SQL. –

risposta

5

Qualcosa del genere dovrebbe ottenere ciò che state cercando:

select 
    id, 
    case 
     when cnt = (select count(distinct type) from t2) 
     then 'All' 
     else ltrim(sys_connect_by_path(type,' & '),' &') 
    end types 
from (
    select 
     t1.id, 
     t2.type, 
     count(*) over (partition by t1.id) cnt, 
     row_number() over (partition by t1.id order by t2.type) rn 
    from 
     t1 
     inner join t2 
      on t2.type = t1.type 
) 
where 
    rn = cnt 
    start with rn = 1 
    connect by prior id = id and prior rn = rn-1; 

darei la tua domanda 10 se potessi per la pubblicazione lo script oggetto/creazione di dati!

+1

Non sarebbe sufficiente un 'GROUP BY Type 'e una funzione di aggregazione invece di sys_connect_by_path? –

+3

Sì, potresti ottenere la stessa soluzione se crei una funzione di aggregazione personalizzata che chiami anche con un gruppo (simile alla funzione stragg che è piuttosto comune). Naturalmente non è più "solo SQL" ... :) – Craig

+3

Se hai 11g puoi invece utilizzare la funzione di analisi LISTAGG: http://download.oracle.com/docs/cd/E11882_01/server.112 /e17118/functions089.htm –

Problemi correlati