SQL : WHERE 절 내의 IF 절


203

MS SQL 의 WHERE 절 내에서 IF 절 을 사용할 수 있습니까?

예:

WHERE
    IF IsNumeric(@OrderNumber) = 1
        OrderNumber = @OrderNumber
    ELSE
        OrderNumber LIKE '%' + @OrderNumber + '%'

답변:


212

CASE 문 사용
UPDATE : 이전 구문 (몇 사람이 지적한대로)이 작동하지 않습니다. 다음과 같이 CASE를 사용할 수 있습니다.

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

또는 @ NJ Reed 와 같은 IF 문을 사용할 수 있습니다 .


[작성자에 의한 업데이트 후 참고 사항] : 작동하지만 일치하는 항목이 있는지 확인하려면 양쪽을 TRIM ()해야합니다. 나는 일치하지 않는 드문 스틸 케이스가 있다고 생각합니다.
Euro Micelli

1
CASE대부분의 경우 적절한 솔루션을 사용하는 것이 좋습니다. 필자의 경우 비교 연산자를 변경하고 싶었으므로 다음 접근 방식을 사용했습니다.
Birla

142

IF 또는 CASE 없이이 작업을 수행 할 수 있어야합니다

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

SQL의 특징에 따라 내재 된 캐스트가 지원되는지 여부에 따라 주문 번호의 캐스트를 INT 또는 VARCHAR로 조정해야 할 수도 있습니다.

이것은 WHERE 절에서 매우 일반적인 기술입니다. WHERE 절에 "IF"논리를 적용하려면 부울 AND가있는 추가 조건을 적용 할 섹션에 추가하면됩니다.


2
CASE 솔루션에 비해 약간의 성능 저하가 있다고 생각합니다. 모든 조건이 평가되기 때문에 아니오?
Kevin Fairchild

나는 항상 SQL에서 조건문을 그런 부울 논리로 바꿀 수 있다는 것을 잊어 버립니다. 알림 주셔서 감사합니다, 그것은 매우 유용한 기술입니다!
CodexArcanum

1
이 솔루션은 실제로 SQL Server가 부울 논리를 처리하는 방식으로 인해 가장 좋습니다. 첫 번째 검사가 실패하면 SQL은 행 처리를 중지하고 계속하기 때문에 where 절이 부울 경우보다 비효율적 인 CASE 문입니다. 처리 시간이 절약됩니다. 또한, 부울 수표의 반대편에 항상 더 많은 비용이 드는 진술을하십시오.
스티브

매우 우아한 솔루션에 감사드립니다. 사람들에게 도움이 될 수있는 방법에 대한 자습서를 찾았습니다. weblogs.sqlteam.com/jeffs/archive/2003/11/14/513.aspx
Rich

1
당신이 제공 한 링크가 읽을 수있는 @Kash, 당신이 말하는 것을 설명하는 공개 문서가 있습니까?
Steve

29

IF 문이 전혀 필요하지 않습니다.

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

2
나는이 접근법을 정말로 좋아한다. Alternativ의 용도 : AdmUseId에 값이있는 경우에만 필터 : where (@AdmUserId is null or CurrentOrder.CustomerAdmUserId = @AdmUserId) 또는 전용 필터의 경우 IncludeDeleted = 0 : where (@IncludeDeleted = 1 or ItemObject.DeletedFlag = 0)
카스퍼 Halvas 젠슨

이것은 WHERE 절 내에서 IN 필터를 사용할 때 잘 작동합니다. COALESCE를 사용해야하기 때문에 CASE 로이 작업을 망칠 수 있으며 읽기가 쉽지 않지만 읽기 쉬운 논리입니다. NOT IN 또는 IN 필터에 대한 WHERE 절의 TSQL CASE 문
pholcroft

14

SQL에서 이것을 수행하는 좋은 방법은 없습니다. 내가 본 몇 가지 접근법 :

1) 부울 연산자와 결합 된 CASE를 사용하십시오.

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) SELECT 외부에서 IF 사용

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

3) 긴 문자열을 사용하여 조건부로 SQL 문을 작성한 다음 EXEC를 사용하십시오.

세 번째 접근 방식은 끔찍하지만, 여러 가지 가변 조건이있는 경우 효과가있는 유일한 방법입니다.


네 번째 방법은 위의 @ njr101 답변에서 와 같이 모든 IF...ELSE...조건부를 부울 AND및 로 변환하는 것 OR입니다. ^이 방법의 단점은이 방법은 IF많은 것이 있거나 중첩 된 것이 많으면 두뇌가 어려울 수 있다는 것입니다.
Don Cheadle


4

CASE 문을 원합니다

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

3

where ... like / = ... case ... then ... 부울과 함께 작동 할 수 있다고 생각합니다. T-SQL을 사용하고 있습니다.

시나리오 : bool이 거짓이면 Person-30의 취미를, bool이 참이면 Person-42의 취미를 원한다고 가정 해 봅시다. (일부에 따르면, 취미 조회는 비즈니스 계산주기의 90 % 이상을 구성하므로 가까운 지불금을 지불하십시오.)

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;

2
어디서? (IsNumeric (@OrderNumber) <> 1 OR OrderNumber = @OrderNumber) 
             AND (IsNumber (@OrderNumber) = 1 또는 '%'와 같은 OrderNumber 
                                              + @ 주문 번호 + '%')

논리 곱 표준형 재 작성 규칙 :IF P THEN Q ELSE R <=> ( ( NOT P ) OR Q ) AND ( P OR R )
onedaywhen

1

CASE 문은 항상 IF 보다 더 나은 옵션 입니다.

  WHERE  vfl.CreatedDate >= CASE WHEN @FromDate IS NULL THEN vfl.CreatedDate ELSE  @FromDate END
    AND vfl.CreatedDate<=CASE WHEN @ToDate IS NULL THEN vfl.CreatedDate ELSE @ToDate END 

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

경우에 따라 조건이 제대로 작동합니다.


0

다음 예제는 부울 표현식의 일부로 쿼리를 실행 한 다음 부울 표현식의 결과에 따라 약간 다른 명령문 블록을 실행합니다. 각 명령문 블록은 BEGIN으로 시작하고 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

중첩 된 IF ... ELSE 문 사용 다음 예는 IF… ELSE 문을 다른 명령문 안에 중첩하는 방법을 보여줍니다. 각 명령문을 테스트하려면 @Number 변수를 5, 50 및 500으로 설정하십시오.

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

2
이것은 관련이없는 것 같습니다. WHERE 절에서 IF (또는 조건부 코드)를 사용하지 않습니다.
빈스 Bowdren

0

SQL Server에서 동일한 문제가 발생했습니다. 매개 변수가 false 인 경우에만 and 문을 사용하고 싶었고 true로 설정하면 true와 false 값을 모두 표시해야 하므로이 방법으로 사용했습니다

(T.IsPublic = @ShowPublic or  @ShowPublic = 1)

-1
If @LstTransDt is Null
                begin
                    Set @OpenQty=0
                end
            else
                begin
                   Select   @OpenQty=IsNull(Sum(ClosingQty),0)  
                   From  ProductAndDepotWiseMonitoring  
                   Where   Pcd=@PCd And PtpCd=@PTpCd And TransDt=@LstTransDt      
                end 

이것이 도움이되는지보십시오.


-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

이것은 관련이없는 것 같습니다. WHERE 절에서 IF (또는 조건부 코드)를 사용하지 않습니다.
빈스 Bowdren
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.