2010-03-23 16 views
18

Tengo dos tablas. indRailType contiene una lista de nombres emparejados con un valor de ID que utilizo en otras tablas para indicar el tipo de raíl. WO_BreakerRail contiene una columna de fecha y una columna de código de carril que corresponde al mismo código en indRailType y algunos otros datos. Hay una fila en WO_BreakerRail para cualquier actividad en cada tipo de riel, para cada fecha. Así que podría tener 3 filas fechadas para 3/19/2010, cada fila indica un código de ferrocarril diferente, y lo que sucedió.JUNTA EXTERIOR IZQUIERDA con una cláusula WHERE

Cuando uso el siguiente LEFT OUTER JOIN, obtengo una tabla con todos los tipos de rieles, con nulos en las filas donde nada ocurrió el día 19. Ahora, esto solo funciona porque solo tengo una fecha representada en mi tabla WO_BreakerRail en este momento, el día 19. Cuando agregue más filas con diferentes fechas, las cosas se pondrán feas.

Esta es mi declaración SQL, que en este momento me da exactamente los resultados que quiero:

SELECT WO_BreakerRail.ID, indRailType.RailType, WO_BreakerRail.CreatedPieces, 
    WO_BreakerRail.OutsideSource, WO_BreakerRail.Charged, 
    WO_BreakerRail.Rejected, WO_BreakerRail.RejectedToCrop 
FROM indRailType 
LEFT OUTER JOIN WO_BreakerRail 
    ON indRailType.RailCode = WO_BreakerRail.RailCode 

Ahora, cuando agrego en una cláusula WHERE WO_BreakerRail.Date = @Date pierdo todas las filas de la JOIN el que no pasó nada. No quiero eso. Desde la lectura, suena como que es LO QUE QUIERO es OUTER JOIN COMPLETO, pero SQL Server Compact Edition no es compatible con FULL OUTER JOIN s. ¿Hay alguna forma de evitar esto o estoy buscando algo completamente distinto?

Respuesta

35

Probar:

SELECT WO_BreakerRail.ID, indRailType.RailType, WO_BreakerRail.CreatedPieces, 
    WO_BreakerRail.OutsideSource, WO_BreakerRail.Charged, 
    WO_BreakerRail.Rejected, WO_BreakerRail.RejectedToCrop 
FROM indRailType 
LEFT OUTER JOIN WO_BreakerRail ON indRailType.RailCode = WO_BreakerRail.RailCode 
      AND WO_BreakerRail.Date = @Date 

Por lo tanto la adición de AND WO_BreakerRail.Date = @Date sobre el unirse

+1

No olvide incluir la porción de "tiempo" de @Date. Si los valores pueden variar entre la medianoche y la medianoche, tendrá que usar alguna forma de cláusula between. –

+0

Esta respuesta funcionó perfectamente, gracias. Philip: Gracias por ese puntero, aunque me encontré con ese problema anteriormente en este proyecto que me dejó perplejo por un tiempo, pero terminé solucionándolo en mi código C#, eliminando todas las partes del tiempo, predeterminando cada fecha hasta la medianoche. – Wesley

+1

@Wesley, lo mejor es "plantar" los tipos de datos de fecha y hora para eliminar el tiempo, por lo que la hora es 00: 00: 00.000 y no la medianoche. –

2

añadir el WO_BreakerRail.Date = @Date en la cuenta de LEFT OUTER JOIN y no WHERE:

SELECT 
    WO_BreakerRail.ID, indRailType.RailType, WO_BreakerRail.CreatedPieces, WO_BreakerRail.OutsideSource, WO_BreakerRail.Charged, WO_BreakerRail.Rejected, WO_BreakerRail.RejectedToCrop 
    FROM indRailType 
     LEFT OUTER JOIN WO_BreakerRail ON indRailType.RailCode = WO_BreakerRail.RailCode AND WO_BreakerRail.Date = @Date 

o puede agregarlo a la DONDE:

SELECT 
    WO_BreakerRail.ID, indRailType.RailType, WO_BreakerRail.CreatedPieces, WO_BreakerRail.OutsideSource, WO_BreakerRail.Charged, WO_BreakerRail.Rejected, WO_BreakerRail.RejectedToCrop 
    FROM indRailType 
     LEFT OUTER JOIN WO_BreakerRail ON indRailType.RailCode = WO_BreakerRail.RailCode 
    WHERE (WO_BreakerRail.Date = @Date OR WO_BreakerRail.Date IS NULL) 
5

puede utilizar esta cláusula where:

WHERE WO_BreakerRail.Date = @Date OR WO_BreakerRail.Date IS NULL 
+3

Cuando se trabaja con combinaciones externas, lo mejor es f actor cualquier "trabajo isnull" en la cláusula ON, y no en la cláusula where –

15

La condición predicado necesita estar en la cláusula On para la combinación, no en la cláusula WHERE. La forma en que las uniones externas funcionan, es después de analizar las condiciones de unión, todas las filas del "lado externo" que no coinciden con el lado interno se vuelven a agregar ... Pero todo esto sucede antes de que se procese la cláusula where. Entonces, si el predicado de la cláusula where filtra un atributo desde el lado externo de una unión externa, todas esas filas se eliminarán nuevamente ... (Todas son nulas). Ponga el predicado en la condición de unión en su lugar, a continuación, se evalúa antes de obtener las filas que faltan se añaden de nuevo en ...

SELECT b.ID, t.RailType, b.CreatedPieces, 
     b.OutsideSource, b.Charged, b.Rejected, 
     b.RejectedToCrop 
FROM indRailType t 
    LEFT JOIN WO_BreakerRail b 
     ON t.RailCode = b.RailCode 
      And b.Date = @Date 
0

Lo que se quiere es filtrar su WO_BreakerRail hasta la fecha deseada antes IZQUIERDA uniéndola a indRailType. Si solo agrega la instrucción WHERE, se hace al revés, lo que da como resultado el problema que describió.

Las soluciones aportadas hasta ahora debería funcionar (mover la condición en la combinación izquierda), pero me gustaría sugerir una alternativa: Se puede utilizar una subconsulta para especificar el orden en que deben hacerse las cosas:

SELECT R.ID, indRailType.RailType, R.CreatedPieces, R.OutsideSource, R.Charged, R.Rejected, R.RejectedToCrop 
    FROM indRailType LEFT OUTER JOIN 
     (SELECT * FROM WO_BreakerRail WHERE Date = @Date) R 
     ON indRailType.RailCode = R.RailCode 

(no probado, pero por lo que yo sé, SQL Server CE admite subconsultas.)

1

o puede agregarlo a la WHERE:

SELECT WO_BreakerRail.ID, indRailType.RailType, 
    WO_BreakerRail.CreatedPieces, 
    WO_BreakerRail.OutsideSource, WO_BreakerRail.Charged, 
    WO_BreakerRail.Rejected, WO_BreakerRail.RejectedToCrop 
FROM indRailType, WO_BreakerRailCode 
WHERE indRailType.RailCode = WO_BreakerRail.RailCode(+) 
AND WO_BreakerRail.Date (+) [email protected] 
+0

El '(+)' es un Operador de Unión de Oracle y el OP está utilizando el Servidor SQL. Además, esa sintaxis para las uniones externas no se recomienda para su uso, ya que es más limitada y más difícil de leer que la sintaxis estándar 'Left Join'. [Oracle Docs: se une] (https://docs.oracle.com/cd/B19306_01/server.102/b14200/queries006.htm) – Wayne

Cuestiones relacionadas