2011-12-02 17 views
21

me gustaría devolver múltiples valores en mi declaración del caso, tales como:declaración de caso en SQL, ¿cómo devolver múltiples variables?

SELECT 
    CASE 
    WHEN <condition 1> THEN <value1=a1, value2=b1> 
    WHEN <condition 2> THEN <value1=a2, value2=b2> 
    ELSE <value1=a3, value3=b3> 
    END 
FROM <table> 

Por supuesto que puedo escribir la condición caso varias veces, cada vez un valor de retorno. Sin embargo, como tengo que ajustar muchas condiciones, digamos 100. No es bueno repetir la condición del caso una y otra vez.

Otra pregunta que me gustaría hacer, ¿qué pasa si un registro se ajusta a varias condiciones? ¿Eso significa que devolverá todos o solo el último? p.ej. la condición 1 puede convertirse en un subconjunto de la condición 2. ¿Qué sucederá?

+0

¿Es esto MS SQL Server? – MatBailie

+0

sí, es ...... – yzhang

+0

¿Puede aclarar su situación? Por ejemplo, ¿las 100 condiciones de caso diferentes conducen a 100 valores aplicables diferentes para cada valor1 y valor2, o muchas de las 100 condiciones diferentes producirán los mismos resultados? ¿Son todas las condiciones completamente combinaciones de diferentes campos, o son diferentes valores posibles de un solo campo? –

Respuesta

13

La forma básica, desafortunadamente, es repetirse.

SELECT 
    CASE WHEN <condition 1> THEN <a1> WHEN <condition 2> THEN <a2> ELSE <a3> END, 
    CASE WHEN <condition 1> THEN <b1> WHEN <condition 2> THEN <b2> ELSE <b3> END 
FROM 
    <table> 

Afortunadamente, la mayoría de los RDBMS son lo suficientemente inteligentes como para NO tener que evaluar las condiciones varias veces. Es solo tipeo redundante.


En MS SQL Server (2005+) que podría CRUZ posible uso se aplican como una alternativa a esto. Aunque no tengo idea de lo que es ... performant

SELECT 
    * 
FROM 
    <table> 
CROSS APPLY 
    (
    SELECT a1, b1 WHERE <condition 1> 
    UNION ALL 
    SELECT a2, b2 WHERE <condition 2> 
    UNION ALL 
    SELECT a3, b3 WHERE <condition 3> 
) 
    AS case_proxy 

La desventaja notable aquí es que no hay equivalente ELSE y como todas las condiciones podrían todos los valores de retorno, tienen que estar enmarcada tal que sólo uno puede ser verdad a la vez.


EDITAR

Si la respuesta de Yuck se cambia a una unión en lugar de JOIN enfoque, se hace muy similar a este. La principal diferencia, sin embargo, es que esto solo escanea el conjunto de datos de entrada una vez, en lugar de una vez por condición (100 veces en su caso).


EDITAR

También he notado que puede significar que los valores devueltos por las instrucciones CASE son fijos. Todos los registros que coinciden con la misma condición obtienen los valores exactos de sames en value1 y value2. Esto podría formarse así ...

WITH 
    checked_data AS 
(
    SELECT 
    CASE WHEN <condition1> THEN 1 
     WHEN <condition2> THEN 2 
     WHEN <condition3> THEN 3 
     ... 
     ELSE     100 
    END AS condition_id, 
    * 
    FROM 
    <table> 
) 
, 
    results (condition_id, value1, value2) AS 
(
    SELECT 1, a1, b1 
    UNION ALL 
    SELECT 2, a2, b2 
    UNION ALL 
    SELECT 3, a3, b3 
    UNION ALL 
    ... 
    SELECT 100, a100, b100 
) 
SELECT 
    * 
FROM 
    checked_data 
INNER JOIN 
    results 
    ON results.condition_id = checked_data.condition_id 
6

Una declaración CASE puede devolver solo un valor.

Puede convertir esto en una subconsulta y luego JOIN en cualquier otra relación con la que esté trabajando. Por ejemplo (utilizando SQL Server 2K5 + CTEs):

WITH C1 AS (
    SELECT a1 AS value1, b1 AS value2 
    FROM table 
    WHERE condition1 
), C2 AS (
    SELECT a2 AS value1, b2 AS value2 
    FROM table 
    WHERE condition2 
), C3 AS (
    SELECT a3 AS value1, b3 AS value2 
    FROM table 
    WHERE condition3 
) 
SELECT value1, value2 
FROM -- some table, joining C1, C2, C3 CTEs to get the cased values 
; 
+0

En lugar de unirse (probablemente uniones externas con declaraciones de fusión), es probable que UNION estos juntos. Con la suposición de que solo una condición es verdadera para un registro de entrada dado. Incluso entonces, esto implicaría escanear el conjunto de datos de origen una vez para cada condición, y así tener 100 escaneos de los datos. – MatBailie

+0

@Dems: Sí, eso funcionaría también. La condición 'ELSE' en la pregunta OP está escrita' ELSE ', por lo que las columnas no son todas idénticas. Lo "solucioné" en mi respuesta, pero puede que no sea un error tipográfico. – Yuck

+0

Buen lugar, no * supongo * un error tipográfico, puede ser relevante, y por lo tanto requiere valores NULL en value2 para otros resultados. – MatBailie

5

CASE por definición, sólo devuelve un solo valor. Nunca.

También (casi siempre) cortocircuitos, lo que significa que si se cumple su primera condición no se ejecutan otras comprobaciones.

+0

+1 ¿Hay alguna condición en la que * no * cause un cortocircuito? –

+0

@MarkBannister - sí, pero tienen errores (en SQL Server). Básicamente, la única circunstancia que he visto es donde haces una comparación con un agregado de una variable ('CASE WHEN MAX (@var) ...'). Los evaluará a todos pero aún devolverá el valor correcto. – JNK

0

Puede usar una subselección combinada con UNIÓN. Siempre que pueda devolver los mismos campos para más de un uso condición OR con el paréntesis como en este ejemplo:

SELECT * FROM 
    (SELECT val1, val2 FROM table1 WHERE (condition1 is true) 
            OR (condition2 is true)) 
UNION 
SELECT * FROM 
    (SELECT val5, val6 FROM table7 WHERE (condition9 is true) 
            OR (condition4 is true)) 
+0

Y para las otras 99 condiciones? (Esto da 2 campos, pero solo para 1 condición) – MatBailie

+0

Use UNION, una subconsulta por condición. –

+0

@Dems: también podría usar 'O' aquí, (edito mi ejemplo para que se ajuste) –

0

en una cláusula CASE SQL, la primera condición adaptada con éxito se aplica y se ignoran cualesquiera condiciones que coinciden posteriores .

2

En su caso, utilizaría dos staements de caja, uno para cada valor que desee devolver.

Cuestiones relacionadas