2011-03-09 18 views
6

Tengo un conjunto de tablas que lógicamente son una tabla dividida en partes por motivos de rendimiento. Necesito escribir una consulta que combine efectivamente todas las tablas, así que utilizo una sola cláusula where del resultado. He utilizado con éxito una UNION en el resultado del uso de la cláusula WHERE en cada subtabla de forma explícita como en el siguiente¿Cómo puedo tratar una consulta UNION como una consulta secundaria?

SELECT * FROM FRED_1 WHERE CHARLIE = 42 
UNION 
SELECT * FROM FRED_2 WHERE CHARLIE = 42 
UNION 
SELECT * FROM FRED_3 WHERE CHARLIE = 42 

pero como hay diez sub-tablas separadas actualización de la cláusula WHERE cada vez es doloroso. Lo que quiero es algo como esto

SELECT * 
FROM (
    SELECT * FROM FRED_1 
    UNION 
    SELECT * FROM FRED_2 
    UNION 
    SELECT * FROM FRED_3) 
WHERE CHARLIE = 42 

Si se hace una diferencia la consulta necesita para funcionar contra una base de datos DB2.

Aquí hay una versión más completa (desinfectada) de lo que tengo que hacer.

select * 
from (select * from FRD_1 union select * from FRD_2 union select * from FRD_3) as FRD, 
    (select * from REQ_1 union select * from REQ_2 union select * from REQ_3) as REQ, 
    (select * from RES_1 union select * from RES_2 union select * from RES_3) as RES 
where FRD.KEY1 = 123456 
    and FRD.KEY1 = REQ.KEY1 
    and FRD.KEY1 = RES.KEY1 
    and REQ.KEY2 = RES.KEY2 

NUEVA INFORMACIÓN:

Parece que el problema tiene más que ver con el número de campos en la unión que cualquier otra cosa. Si restrinjo mucho los campos, puedo obtener la mayoría de las variaciones de sintaxis que están por debajo. Desafortunadamente, restringir tanto los campos significa que la consulta resultante, aunque potencialmente útil, no me da el resultado que quería. Logré obtener 3 campos adicionales de una de las tablas además de las 2 claves. Más que eso y la consulta falla.

+3

¿Eso sintaxis producir un error? Si usa UNION ALL en lugar de UNION, podría funcionar bien. Luego pones los sindicatos a la vista y has reinventado la partición ... – araqnid

+0

¿Te das cuenta de que esta estrategia de "dividir la mesa" es una técnica de pesimismo identificada? – dkretz

+0

De hecho, tuve que buscar lo que significaba pesimismo :-) Habiendo dicho eso, la idea de dividir la tabla es parte de una aplicación de unos 10 años de antigüedad, así que no puedo hacer mucho al respecto. –

Respuesta

24

Creo que tiene que dar un nombre al resultado de su subconsulta. No sé db2, así que estoy tomando una foto en la oscuridad, pero sé que esto funciona en muchas otras plataformas.

SELECT * 
FROM (
    SELECT * FROM FRED_1 
    UNION 
    SELECT * FROM FRED_2 
    UNION 
    SELECT * FROM FRED_3) AS T1 
WHERE CHARLIE = 42 
+0

Esto funciona en el caso simple de un grupo de tablas (unión) pero no funciona si deseo unirme a otro grupo similar T2 –

+0

¿Su consulta original produce un error o simplemente no devuelve los resultados que deseaba? – Infotekka

+0

Recibo el error SQL0136, SQLCODE -136, SQLSTATE 54005 que significa "ORDEN POR o GRUPO POR columnas demasiado largas". El problema es que obtengo esto a pesar de que no tengo un ORDER BY o GROUP BY en mi consulta. Sí, tengo 30 tablas (3 grupos de 10, cada grupo relacionado con el siguiente por clave (T1.KEY = T2.KEY y T2.KEY = T3.KEY y T2.KEY2 = T3.KEY2)) –

1

no estoy familiarizado con la sintaxis de DB2 pero ¿por qué no haces esto como un INNER JOIN o LEFT JOIN?

SELECT * 
    FROM FRED_1 
INNER JOIN FRED_2 
    ON FRED_1.Charlie = FRED_2.Charlie 
INNER JOIN FRED_3 
    ON FRED_1.Charlie = FRED_3.Charlie 
WHERE FRED_1.Charlie = 42 

Si no existen los valores en FRED_2 o FRED_3 luego usar un LEFT/OUTER JOIN. Supongo que FRED_1 es una tabla maestra, y si existe un registro, estará en esta tabla.

+0

En realidad, FRED es una tabla dividida en varias partes 1-10, una clave aparecerá en una y solo una de estas subtablas –

2

Si la implementación lógica es una sola tabla, pero la implementación física es de varias tablas, ¿qué hay de la creación de una vista que define el modelo lógico.

CREATE VIEW VW_FRED AS 
SELECT * FROM FRED_1 
UNION  
SELECT * FROM FRED_2 
UNION  
SELECT * FROM FRED_3 

entonces es una simple cuestión de

SELECT * FROM VW_FRED WHERE CHARLIE = 42 

Una vez más, no estoy familiarizado con la sintaxis de DB2, pero esto le da la idea general.

+0

Esto sería genial, si tuviera permiso para crear vistas ... localmente DB2 instalado en mainframe "necesita" DB2 grupo para "gestionar" todas las modificaciones incluso para DEV. –

0
with 
FRD as (select * from FRD_1 union select * from FRD_2 union select * from FRD_3), 
REQ as (select * from REQ_1 union select * from REQ_2 union select * from REQ_3), 
RES as (select * from RES_1 union select * from RES_2 union select * from RES_3) 
SELECT * from FRD, REQ, RES 
WHERE FRD.KEY1 = 123456 
and FRD.KEY1 = REQ.KEY1 
and FRD.KEY1 = RES.KEY1 
and REQ.KEY2 = RES.KEY2 
+0

Obtengo SQLCODE -136 SQLSTATE 54005 (La clave de clasificación es demasiado larga, o tiene demasiadas columnas) tan pronto como incluyo alguna unión. Esta sintaxis funciona si no especifico uniones. –

0

quizá:

SELECT * FROM 
(select * from FRD_1 
union 
select * from FRD_2 
union 
select * from FRD_3) FRD 
INNER JOIN (select * from REQ_1 union select * from REQ_2 union select * from REQ_3) REQ 
    on FRD.KEY1 = REQ.KEY1 
INNER JOIN (select * from RES_1 union select * from RES_2 union select * from RES_3) RES 
    on FRD.KEY1 = RES.KEY1 
WHERE FRD.KEY1 = 123456 and REQ.KEY2 = RES.KEY2 
+0

Obtengo el mismo problema (SQLSTATE 54005) al intentar esto y las variaciones –

+0

¿necesita todos los campos de todas las tablas? ¿tal vez especificando campos específicos no tendrá demasiadas columnas para la clave de clasificación? – Leslie

+0

Lo intenté y solo puedo obtener tres campos adicionales (distintos de las dos teclas). Eso no es útil para mí en la mayoría de los casos –

Cuestiones relacionadas