2008-09-17 17 views

Respuesta

167

utilizar una instrucción CASE
ACTUALIZACIÓN: La sintaxis anterior (como se ha señalado por unas pocas personas) no funciona. Puede utilizar CASO de la siguiente manera:

WHERE OrderNumber LIKE 
    CASE WHEN IsNumeric(@OrderNumber) = 1 THEN 
    @OrderNumber 
    ELSE 
    '%' + @OrderNumber 
    END 

O puede utilizar una instrucción IF como @N. J. Reed señala.

+0

[Nota después de la ACTUALIZACIÓN por el autor]: Eso debería funcionar, pero debe TRIM() ambas partes para asegurarse de que se encuentra una coincidencia. Tengo la intuición de que hay casos aún poco comunes que no coinciden. –

+1

El uso de 'CASE' es la solución adecuada en la mayoría de los casos. En mi caso, quería cambiar el operador de comparación y, por lo tanto, utilicé el siguiente enfoque. – Birla

6

utilizar una instrucción en lugar de SI CASE.

4

desea que el comando CASE

WHERE OrderNumber LIKE 
CASE WHEN IsNumeric(@OrderNumber)=1 THEN @OrderNumber ELSE '%' + @OrderNumber END 
117

Usted debe ser capaz de hacer esto sin ningún IF o CASE

WHERE 
    (IsNumeric(@OrderNumber) AND 
     (CAST OrderNumber AS VARCHAR) = (CAST @OrderNumber AS VARCHAR) 
OR 
    (NOT IsNumeric(@OrderNumber) AND 
     OrderNumber LIKE ('%' + @OrderNumber)) 

Dependiendo del sabor de SQL es posible que tenga que modificar los moldes en la número de orden a INT o VARCHAR dependiendo de si los moldes implícitos son compatibles.

Esta es una técnica muy común en una cláusula WHERE. Si desea aplicar alguna lógica "IF" en la cláusula WHERE, todo lo que necesita hacer es agregar la condición adicional con un booleano Y a la sección donde se debe aplicar.

+1

Supongo que tendrá un poco de rendimiento sobre la solución CASE, ya que todas esas condiciones se evalúan, ¿no? –

+0

Perfecto: resolvió un problema de larga data para mí; gracias por el puntero! – cori

+0

Siempre olvido que en SQL se pueden reemplazar las sentencias condicionales con lógica booleana como esa. Gracias por el recordatorio, ¡es una técnica muy útil! – CodexArcanum

13

No hay una buena manera de hacer esto en SQL. Algunos enfoques que he visto:

1) Caso de uso combinado con los operadores booleanos:

WHERE 
    OrderNumber = CASE 
     WHEN (IsNumeric(@OrderNumber) = 1) 
     THEN CONVERT(INT, @OrderNumber) 
     ELSE -9999 -- Some numeric value that just cannot exist in the column 
    END 
    OR 
    FirstName LIKE CASE 
     WHEN (IsNumeric(@OrderNumber) = 0) 
     THEN '%' + @OrderNumber 
     ELSE '' 
    END 

2) Uso SI de fuera del SELECT

IF (IsNumeric(@OrderNumber)) = 1 
BEGIN 
    SELECT * FROM Table 
    WHERE @OrderNumber = OrderNumber 
END ELSE BEGIN 
    SELECT * FROM Table 
    WHERE OrderNumber LIKE '%' + @OrderNumber 
END 

3) El uso de una cadena larga, componen su SQL declaración condicionalmente, y luego utilice EXEC

El tercer enfoque es horrible, pero es casi lo único que funciona si tiene varias condiciones variables como esa.

+0

el cuarto enfoque es convertir todos tus condicionales 'IF ... ELSE ...' en 'AND' y 'OR' de boolean como en la respuesta @ njr101 anterior. La desventaja de este enfoque es que puede ser muy difícil si tienes muchos 'IF', o si tienes muchos que están anidados – mmcrae

3

Creo que donde ... como/= ... caso ... entonces ... puede trabajar con booleanos. Estoy usando T-SQL.

Escenario: Supongamos que quiere obtener los pasatiempos de Persona-30 si bool es falso, y los pasatiempos de Persona-42 si bool es cierto. (Según algunos, las búsquedas de pasatiempos comprenden más del 90% de los ciclos de computación de negocios, así que pague de cerca).

CREATE PROCEDURE sp_Case 
@bool bit 
AS 
SELECT Person.Hobbies 
FROM Person 
WHERE Person.ID = 
    case @bool 
     when 0 
      then 30 
     when 1 
      then 42 
    end; 
1
 
WHERE (IsNumeric(@OrderNumber) <> 1 OR OrderNumber = @OrderNumber) 
      AND (IsNumber(@OrderNumber) = 1 OR OrderNumber LIKE '%' 
               + @OrderNumber + '%') 
+0

Conjuntivo Normal Forma reescribe la regla: 'SI P THEN Q ELSE R'' <=> ' '((NOT P) O Q) AND (P OR R)' – onedaywhen

-6
USE AdventureWorks2012; 
GO 
IF 
(SELECT COUNT(*) FROM Production.Product WHERE Name LIKE 'Touring-3000%') > 5 
PRINT 'There are more than 5 Touring-3000 bicycles.' 
ELSE PRINT 'There are 5 or less Touring-3000 bicycles.' ; 
GO 
+0

Esto no parece relevante. No utiliza un IF (o cualquier código condicional) en una cláusula WHERE. –

0

El siguiente ejemplo ejecuta una consulta como parte de la expresión booleana y luego ejecuta ligeramente diferentes bloques de instrucciones basadas en el resultado de la expresión booleana.Cada bloque de instrucción comienza con BEGIN y finaliza con END.

USE AdventureWorks2012; 
GO 
DECLARE @AvgWeight decimal(8,2), @BikeCount int 
IF 
(SELECT COUNT(*) FROM Production.Product WHERE Name LIKE 'Touring-3000%') > 5 
BEGIN 
    SET @BikeCount = 
     (SELECT COUNT(*) 
     FROM Production.Product 
     WHERE Name LIKE 'Touring-3000%'); 
    SET @AvgWeight = 
     (SELECT AVG(Weight) 
     FROM Production.Product 
     WHERE Name LIKE 'Touring-3000%'); 
    PRINT 'There are ' + CAST(@BikeCount AS varchar(3)) + ' Touring-3000 bikes.' 
    PRINT 'The average weight of the top 5 Touring-3000 bikes is ' + CAST(@AvgWeight AS varchar(8)) + '.'; 
END 
ELSE 
BEGIN 
SET @AvgWeight = 
     (SELECT AVG(Weight) 
     FROM Production.Product 
     WHERE Name LIKE 'Touring-3000%'); 
    PRINT 'Average weight of the Touring-3000 bikes is ' + CAST(@AvgWeight AS varchar(8)) + '.' ; 
END ; 
GO 

anidadas utilizando IF ... ELSE El siguiente ejemplo muestra cómo un IF ... ELSE puede anidarse dentro de otro. Establezca la variable @Number en 5, 50 y 500 para probar cada instrucción.

DECLARE @Number int 
SET @Number = 50 
IF @Number > 100 
    PRINT 'The number is large.' 
ELSE 
    BEGIN 
     IF @Number < 10 
     PRINT 'The number is small' 
    ELSE 
     PRINT 'The number is medium' 
    END ; 
GO 
+1

Esto no parece relevante. No utiliza un IF (o cualquier código condicional) en una cláusula WHERE. –

12

No necesita una declaración IF en absoluto.

WHERE 
    (IsNumeric(@OrderNumber) = 1 AND OrderNumber = @OrderNumber) 
OR (IsNumeric(@OrderNumber) = 0 AND OrderNumber LIKE '%' + @OrderNumber + '%') 
+1

Me gusta mucho este enfoque. Alternativ utiliza: Solo filtra si AdmUseId tiene un valor: 'donde (@AdmUserId es nulo o CurrentOrder.CustomerAdmUserId = @AdmUserId)' O solo filtra si IncludeDeleted = 0: 'donde (@IncludeDeleted = 1 o ItemObject.DeletedFlag = 0) ' –