2010-11-10 6 views
7

He escrito una solución al problema de usar PL/SQL y SQL y no puedo evitar pensar que se podría hacer al 100% en SQL, pero estoy luchando por comenzar.Solución al problema hecho en PL/SQL ¿cómo se vería en SQL?

Aquí está la estructura de las dos tablas (Si ayuda, las secuencias de comandos para crearlos están al final de la cuestión)

tabla T1 (clave principal es ambas columnas mostradas)

ID TYPE 
1  A 
1  B 
1  C 

2  A 
2  B 

3  B 

la columna Tipo es una clave externa a la tabla T2, que contiene los siguientes datos:

tabla T2 (clave principal es Type)

Type Desc 
A  xx 

B  xx 

C  xx 

Por lo tanto, dada la los datos en la T1 el resultado Necesito será:

Por Identificación 1 porque tiene todos los tipos de la tabla de clave externa que volvería el literal "Todos"

Por ID 2 porque tiene dos tipos me gustaría volver "a & B" (nótese el separador)

Y finalmente ID 3, ya que tiene un tipo me gustaría volver sólo "B"

Según lo prometido aquí son los guiones para crear todos los objetos mencionados.

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

¿Va a agregar más tipos en t2? No solo A, B y C? – mcpeterson

+0

@mcpeterson: Gracias por el comentario. Los datos en t2 serán corregidos, con un total de alrededor de 5 filas –

+1

La necesidad de concatenación de cadenas orientadas a grupos anula la capacidad de hacer esto en SQL puro. –

Respuesta

5

Algo como esto debe conseguir lo que busca:

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; 

le daría a su pregunta 10 si pudiera por publicar un/script de creación de datos de objetos!

+1

¿No sería suficiente un 'GROUP BY Type' y una función de agregación en lugar de sys_connect_by_path? –

+3

Sí, podría obtener la misma solución si crea una función de agregado personalizada a la que llame también con un grupo (similar a la función de Stragg que es bastante común). Por supuesto, eso ya no es "solo SQL" ... :) – Craig

+3

Si tiene 11g, puede usar la función analítica LISTAGG en su lugar: http://download.oracle.com/docs/cd/E11882_01/server.112 /e17118/functions089.htm –

Cuestiones relacionadas