¿Puedo utilizar la sentencia CASE en una condición JOIN?

La siguiente imagen es una parte de Microsoft SQL Server 2008 R2 System Views. En la imagen podemos ver que la relación entre sys.partitions y sys.allocation_units depende del valor de sys.allocation_units.type. Así que para unirlos escribiría algo similar a esto:

SELECT  *
FROM    sys.indexes i
        JOIN sys.partitions p
            ON i.index_id = p.index_id 
        JOIN sys.allocation_units a
            ON CASE
               WHEN a.type IN (1, 3)
                   THEN a.container_id = p.hobt_id 
               WHEN a.type IN (2)
                   THEN a.container_id = p.partition_id
               END 

Pero el código superior da un error de sintaxis. Supongo que es por la sentencia CASE. ¿Alguien puede ayudar a explicar un poco?


Añadir mensaje de error:

Msg 102, Nivel 15, Estado 1, Línea 6 Sintaxis incorrecta cerca de '='.

Solución

Una expresión CASE devuelve un valor de la parte THEN de la cláusula. Se puede utilizar de esta manera:

SELECT  * 
FROM    sys.indexes i 
    JOIN sys.partitions p 
        ON i.index_id = p.index_id  
    JOIN sys.allocation_units a 
        ON CASE 
           WHEN a.type IN (1, 3) AND a.container_id = p.hobt_id THEN 1
           WHEN a.type IN (2) AND a.container_id = p.partition_id THEN 1
           ELSE 0
           END = 1

Tenga en cuenta que necesita hacer algo con el valor devuelto, por ejemplo, compararlo con 1. Su declaración intentó devolver el valor de una asignación o probar la igualdad, ninguno de los cuales tiene sentido en el contexto de una cláusula CASE/THEN. (Si BOOLEAN fuera un tipo de dato entonces la prueba de igualdad tendría sentido).

Comentarios (6)

En su lugar, simplemente se hace un JOIN a ambas tablas, y en su cláusula SELECT devuelve los datos de la que coincida:

Te sugiero que veas este enlace Conditional Joins in SQL Server y https://stackoverflow.com/questions/8361183/t-sql-case-statement-in-a-join-on-clause

Por ejemplo

    SELECT  *
FROM    sys.indexes i
        JOIN sys.partitions p
            ON i.index_id = p.index_id 
        JOIN sys.allocation_units a
            ON a.container_id =
            CASE
               WHEN a.type IN (1, 3)
                   THEN  p.hobt_id 
               WHEN a.type IN (2)
                   THEN p.partition_id
               END 

Edición: Según los comentarios.

No se puede especificar la condición de unión como lo estás haciendo.. Comprueba la

consulta de arriba que no tienen ningún error. He sacado la columna común arriba y el valor de la columna de la derecha se evaluará en la condición.

Comentarios (9)

Prueba esto:

...JOIN sys.allocation_units a ON 
  (a.type=2 AND a.container_id = p.partition_id)
  OR (a.type IN (1, 3) AND a.container_id = p.hobt_id)
Comentarios (1)