2010-01-06 21 views
6

Tengo la siguiente consulta T-SQL (un caso de prueba simple) ejecutándose bien en MS SQL pero no puedo obtener la consulta equivalente en MS Access (JET-SQL). El problema es el criterio adicional en LEFT JOIN. ¿Cómo puedo hacer esto en MS Access?UNIÓN IZQUIERDA en criterios adicionales en MS Access

T-SQL:

SELECT * FROM A 
LEFT OUTER JOIN B ON A.ID = B.A_ID 
       AND B.F_ID = 3 

JET-SQL (lo que tengo hasta ahora, pero se bloquea el acceso!):

SELECT * FROM dbo_A 
LEFT JOIN dbo_B ON (dbo_A.ID = dbo_B.A_ID AND dbo_B.F_ID = 3) 
+0

No debería necesitar los corchetes en los criterios de unión –

+0

¿Importa que el ejemplo de T-SQL sea una unión externa? Todo lo que hace básicamente es devolver todas las filas en A. – Melvin

+0

@OMG Ponies - Sin paréntesis, obtengo un error de sintaxis, con ellos, Access se bloquea ... @ Melvin - No, la palabra OUTER es opcional. – Supergibbs

Respuesta

10

Es necesario utilizar una subselección de aplicar la condición:

SELECT * 
    FROM dbo_A LEFT JOIN 
    [SELECT dbo_B.* FROM dbo_B WHERE dbo_B.F_ID = 3]. AS dbo_B 
     ON dbo_A.ID = dbo_B.A_ID; 

Si se está utilizando el acceso con el modo de compatibilidad "SQL 92" está activada, puede hacer lo más estándar:

SELECT * 
    FROM dbo_A LEFT JOIN 
    (SELECT dbo_B.* FROM dbo_B WHERE dbo_B.F_ID = 3) AS dbo_B 
     ON dbo_A.ID = dbo_B.A_ID; 

¿Necesita que se pueda editar en Access? Si no, solo usa una consulta de paso con el T-SQL nativo. Si es así, probablemente crearía una vista del lado del servidor para esto, y me gustaría moverlo especialmente del lado del servidor si el valor literal es algo que usted parametrizaría (es decir, el F_ID = 3 es realmente F_ID = N donde N es un valor elegido en tiempo de ejecución).

BTW, escribo estas sentencias SQL de tablas derivadas de subselección todos los días mientras trabajo en Access. No es un gran problema.

+0

Sí, sé que puedo usar una subselección, pero es significativamente más lenta, así que prefiero usar una combinación de la izquierda. Sin embargo, no sabía acerca de la opción de consulta de paso a través, ¡eso funcionó perfectamente! (más información para otros aquí: http://support.microsoft.com/kb/303968). Estoy marcando su respuesta como aceptada, ya que funcionó. ¡Gracias! – Supergibbs

+1

Si la subselección es más lenta depende de dos cosas: 1) cómo el motor de base de datos involucrado optimiza la subselección frente a la alternativa, y la obvia en este caso, 2) si la opción está disponible o no. En Jet/ACE SQL no es porque no pueda tener una unión de múltiples campos definida en la dirección opuesta (es decir, una de A => B y la otra de B => A). Puede ser que SQL Server optimice la subselección de manera subóptima en comparación con la alternativa, pero si está utilizando Jet/ACE, tendrá que seguir las reglas de Jet/ACE, de ahí la mención de los passthroughs. –

+1

Estoy bastante seguro de que una combinación de la izquierda siempre es más rápida que una subselección. Claro, en un pequeño conjunto de datos o si su motor DB puede optimizar (también puede convertir su subselección en una combinación izquierda) no verá la diferencia, pero "una combinación izquierda luego una selección de n filas" será más rápida que " n + 1 selecciona ". Definitivamente, en mi caso, SQL Server ejecutó la combinación de la izquierda más rápido. – Supergibbs

-4

Esta última exigencia técnicamente no es una unión, pero una comparación a un valor literal. Lo puso en una cláusula WHERE:

SELECT * 
FROM a LEFT OUTER JOIN b ON a.ID = b.a_id 
WHERE b.f_id = 3; 
+5

Eso no es verdad. Verificar F_ID = 3 en la condición de unión izquierda le daría nulo para todos los valores desde B cuando F_ID = 3. Ponerlo en la cláusula where no los devolvería en absoluto. – lins314159

+0

Lo siento, lo que quise decir es que obtienes nulo cuando F_ID <> 3 para un join izquierdo. – lins314159

1

¿Recibe un mensaje de error cuando se rompe o se acaba de encerrar? A juzgar por el nombre dbo_B, voy a adivinar que estas son tablas vinculadas en Access. Creo que cuando haces una combinación como esa, Access no le dice a SQL Server que necesita el resultado de la unión, dice, "Dame todas las filas de ambas tablas" y luego intenta unirse a ellas. Si las tablas son muy grandes, esto puede hacer que la aplicación se bloquee.

Probablemente sea mejor que cree una vista en SQL Server para lo que necesita.

+0

Definitivamente una buena idea, ¿significa eso que mi sintaxis es correcta, solo que Access no puede manejarla? – Supergibbs

+0

No sé si Access tiene un límite técnico, pero si las tablas son millones de filas, entonces la PC en la que se ejecuta Access y la red sobre la que fluyen los datos probablemente se vean abrumadas. –

+0

No es cierto que Jet/ACE solicite la tabla completa y realiza las uniones, a menos que haya algo que impida que Jet/ACE obtenga los metadatos que necesita para determinar si puede pasar todo al servidor (lo que debería ser el caso el 99% del tiempo). O bien, podría ser que haya algo sobre las tablas vinculadas (que podrían ser vistas, por ejemplo) que impida que Jet/ACE haga el trabajo. Esos son los dos únicos casos que se me ocurren que podrían causar que Jet/ACE solicite las tablas completas con el SQL proporcionado.En resumen, es muy, muy poco probable que eso vaya a suceder. –