2011-03-09 26 views
9

Tengo una consulta particularmente complicada para un informe. Selecciona varias columnas de una vista y debe construir una columna mediante la concatenación agregada de varios campos. Para complicar aún más las cosas, la concatenación debe contener 3 campos, incluso si hay 0 en realidad (la concatenación está delimitada por comas, por lo que todavía se notarán los campos vacíos).Subconsulta anidada en SQL que hace referencia a la columna de abuelos

Estamos utilizando Oracle 11.1.0.7.0.

Para proporcionar compatibilidad con versiones anteriores (no es necesario), se utilizó la función XMLAGG para realizar la concatenación, creo que ha existido desde Oracle 8 o 9.

se simplificará este ejemplo, pero me siento proporciona información suficiente. En otras palabras, por favor no se concentre en la normalización de la estructura de la tabla, esto es estrictamente un ejemplo.

person_view 
----------- 
name 
phone 
address 
position_id 


position_table 
-------------- 
position_id 
position_title 

lo que la consulta que tienen actualmente, y me reconocen no ser un gurú de SQL, es algo así como:

select 
    name, 
    phone, 
    address, 
    (select 
    xmlagg(xmlelement(e, position_title || ',')).extract('//text()') 
    from 
    (select 
     position_title 
     from 
     position_table 
     where 
     position_table.position_id = person_view.position_id and 
     rownum <= 3 
     union all select '' from dual 
     union all select '' from dual 
     union all select '' from dual 
    ) 
    where 
    rownum <= 3 
) 
from 
    person_view 

Mi error real es que, al parecer, la subconsulta que asegura al menos 3 filas de entrada no pueden hacer referencia a la consulta de abuelos para determinar person_view.position_id.

me sale ORA-00904: "PERSON_VIEW" "POSITION_ID":. Identificador no válido Rendimiento

no es una gran preocupación, ya que este es un informe que no se pasan con regularidad, pero tengo que encontrar una solución para agregar estos datos con un total de 3 columnas de datos. Cualquier orientación para ayudar a reescribir la consulta, o permitir que la subconsulta tenga acceso a la columna de abuelos correspondiente es muy apreciada.

+3

+1 para la pregunta muy bien escrito. Ojalá todos estuvieran tan claramente presentados. –

Respuesta

3

Esto es una limitación en Oracle SQL: no puede hacer referencia a un elemento de consulta principal desde una subconsulta de más de 1 nivel de profundidad.

me gustaría utilizar una función en tal caso:

CREATE OR REPLACE FUNCTION get_title(p_position_id NUMBER) RETURN VARCHAR2 IS 
    l_result  LONG; 
    l_position_num NUMBER := 0; 
BEGIN 
    FOR cc IN (SELECT position_title 
       FROM position_table 
       WHERE position_table.position_id = p_position_id 
       AND rownum <= 3) LOOP 
     l_result  := cc.position_title || ','; 
     l_position_num := l_position_num + 1; 
    END LOOP; 
    RETURN l_result || rpad(',', 3 - l_position_num, ','); 
END; 

su búsqueda se vería así:

select 
    name, 
    phone, 
    address, 
    get_title(p.position_id) title 
from person_view p 
+0

gracias, lo haré en pl/sql –

+1

¿Es esto una limitación constante o un error? Me encontré con problemas similares antes, pero creo que en teoría debería poder llamar al desde cualquier nivel. Por ejemplo, esta afirmación funciona con 6 niveles (en 10.2.0.1.0): 'select (select (select (select (select (select test.dummy from dual) from dual) from dual) from dual) from dual) from prueba dual; ' –

+1

@jonearles: esta es una limitación constante conocida, consulte por ejemplo [esta pregunta en AskTom] (http://asktom.oracle.com/pls/asktom/f?p=100:11:0 :: :: P11_QUESTION_ID: 1853075500346799932). Su caso es realmente interesante, parece que todavía se considera de un nivel profundo [las subconsultas son todas * subconsultas escalares]. Esto no funciona, por ejemplo: 'SELECT (SELECT xx FROM (SELECCIONAR test.dummy xx FROM dual)) FROM dual test' –

Cuestiones relacionadas