2012-05-08 9 views
5

Tengo una tabla que contiene una columna que actúa como una "bandera" que se usa para decidir desde qué tabla extraer información adicional (es decir, el valor 1 extrae de la tabla1, 2 de table2, etc.). Por lo general, simplemente me uno a la mesa usando índices/claves. Sin embargo, la tabla a la que podía unirme contenía información que se podía normalizar en tablas separadas, lo que me deja en la situación de usar una columna para decidir a qué tabla unirme.SQL Optimization - Unir diferentes tablas basadas en el valor de columna

Así que aquí está mi pregunta, ¿cuál es la forma más eficiente de unir diferentes tablas en función del valor producido en esta columna?

Estas son las dos formas en que sé cómo realizar esta tarea actualmente. Estoy bastante seguro de que son a la vez no es la solución óptima:

  1. Tire de la información de mi mesa principal (que contiene el valor de la columna que decide en qué mesa para unirse), y luego a través de código en mi aplicación enviar consultas adicionales a obtener el resto de la información.

  2. Vaya a la locura, regrese las columnas de cada tabla (incluso si no se usa). Luego, a través de mi código, ignore los nulos de las tablas que no se necesitan.

+2

Qué tal el punto 1. Pero, póngalo en el procedimiento almacenado en lugar del código de la aplicación. –

Respuesta

1

Definitivamente no la opción 2. Si no necesita los datos, no la recupere. Sencillo. Sería increíblemente ineficiente unirse a las tablas (especialmente las grandes) cuando no se necesitan los datos. Puede ir con la opción 1 o usar SQL dinámico para crear la consulta. Luego, comparto algunos casos de prueba y ejecuto el plan de ejecución para ver cómo está funcionando su consulta.

1

Dependiendo del contenido de las otras tablas, sugeriría una UNIÓN: las columnas devueltas deben ser las mismas para cada consulta. Así que usted puede hacer algo como:

SELECT table1.title, tabel2.text FROM table1 INNER JOIN table2 ON table1.id=table2.id WHERE table1.key='2' 
UNION 
SELECT table1.title, tabel3.text FROM table1 INNER JOIN table3 ON table1.id=table3.id WHERE table1.key='3' 

(Optimizando el SQL para asegurarse de que coincida con su esquema, y ​​de hecho para evitar cualquier error que he añadido en)

+0

Cada tabla tiene columnas diferentes a excepción de las claves/índices que utilizaré para unir las tablas, una vez que sepa qué tabla usar. – user1110302

+0

En ese caso, creo que tendrá que realizar varias consultas, una para cada tabla. ¿Aunque podría ser posible TALAR las filas de cada tabla para que todas estén en los mismos tipos? – andrewsi

+0

nota con tablas temporales que no se pueden utilizar en subconsultas/unión más de una vez en mysql – tipu

1

Creo que es posible:

create table a (id integer, flag boolean); 
create table b (id integer, value_b varchar(30)); 
create table c (id integer, value_c varchar(30)); 

insert into a values (1, true), (2, false); 
insert into b values (1, 'Val 1'), (2, 'Val 2'); 
insert into c values (1, 'C 1'), (2, 'C 2'); 

select a.id, 
     case when a.flag then b.value_b else c.value_c end AS value 
    from a 
    left join b using (id) 
    left join c using (id); 

Puede try it out.

Por supuesto hay limitaciones:

  • número de columnas es fijo, por lo que hay que ir por NULL s si algunos valores deben ser omitidos;
  • tendrá que escribir un CASE ... END para cada columna;
  • debe conocer todas las tablas unidas por adelantado;
  • puede que el rendimiento no sea el mejor.
+0

Gracias por la respuesta, pero esto definitivamente no funcionará para mi caso.En este caso, las columnas serán diferentes en cada tabla y, como se mencionó anteriormente, si se unen las otras tablas y no se usa parte de la información, se destruirá el rendimiento inmediatamente. – user1110302

Cuestiones relacionadas