[sql] ‘where’절의 SQL 스위치 / 케이스

나는 주변을 둘러 보려고했지만 나를 도울만한 것을 찾을 수 없었다.

SQL에서 이것을하려고합니다.

declare @locationType varchar(50);
declare @locationID int;

SELECT column1, column2
FROM viewWhatever
WHERE
CASE @locationType
    WHEN 'location' THEN account_location = @locationID
    WHEN 'area' THEN xxx_location_area = @locationID
    WHEN 'division' THEN xxx_location_division = @locationID

각 끝에 끝에 ‘= @locationID’를 넣을 필요는 없지만 구문이 정확하다는 것을 알 수는 없습니다. SQL은 첫 번째 줄에서 내 ‘=’에 대해 계속 불평합니다 …

어떻게해야합니까?



답변

declare @locationType varchar(50);
declare @locationID int;

SELECT column1, column2
FROM viewWhatever
WHERE
@locationID =
  CASE @locationType
      WHEN 'location' THEN account_location
      WHEN 'area' THEN xxx_location_area
      WHEN 'division' THEN xxx_location_division
  END


답변

사례 진술없이 …

SELECT column1, column2
FROM viewWhatever
WHERE
    (@locationType = 'location' AND account_location = @locationID)
    OR
    (@locationType = 'area' AND xxx_location_area = @locationID)
    OR
    (@locationType = 'division' AND xxx_location_division = @locationID)


답변

여기 요

SELECT
   column1,
   column2
FROM
   viewWhatever
WHERE
CASE
    WHEN @locationType = 'location' AND account_location = @locationID THEN 1
    WHEN @locationType = 'area' AND xxx_location_area = @locationID THEN 1
    WHEN @locationType = 'division' AND xxx_location_division = @locationID THEN 1
    ELSE 0
END = 1


답변

나는 이것이 결함이있는 테이블 구조의 지표라고 말하고 싶다. 다른 위치 유형을 다른 테이블로 분리해야하므로 훨씬 더 풍부한 쿼리를 수행하고 불필요한 열을 피할 수 있습니다.

구조를 변경할 수 없으면 다음과 같이 작동 할 수 있습니다.

SELECT
    *
FROM
    Test
WHERE
    Account_Location = (
        CASE LocationType
          WHEN 'location' THEN @locationID
          ELSE Account_Location
        END
    )
    AND
    Account_Location_Area = (
        CASE LocationType
          WHEN 'area' THEN @locationID
          ELSE Account_Location_Area
        END
    )

그리고 등등 … 우리는 쿼리의 구조를 즉석에서 바꿀 수 없지만, 술어 자체를 동일하게 만들어서 그것을 무시할 수 있습니다.

편집 : 위의 제안은 물론 훨씬 낫습니다. 내 것을 무시하십시오.


답변

이것의 문제점은 SQL 엔진이 표현식을 평가할 때 적절한 테이블을 가져 오기 위해 FROM 부분을 확인한 다음 일부 기준을 제공하기 위해 WHERE 부분을 확인하여 열이 어떤 동적 조건을 올바르게 평가할 수 없다는 것입니다 확인하십시오.

술어에서 WHERE 기준을 확인할 때 WHERE 절을 사용할 수 있습니다.

WHERE account_location = CASE @locationType
                              WHEN 'business' THEN 45
                              WHEN 'area' THEN 52
                         END

따라서 특별한 경우 쿼리를 저장 프로 시저에 넣거나 세 개의 별도 쿼리를 만들어야합니다.


답변

OR 연산자는 조건에 따라 대용 할 수 있습니다.

ALTER PROCEDURE [dbo].[RPT_340bClinicDrugInventorySummary]
    -- Add the parameters for the stored procedure here
     @ClinicId BIGINT = 0,
     @selecttype int,
     @selectedValue varchar (50)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
SELECT
    drugstock_drugname.n_cur_bal,drugname.cdrugname,clinic.cclinicname

FROM drugstock_drugname
INNER JOIN drugname ON drugstock_drugname.drugnameid_FK = drugname.drugnameid_PK
INNER JOIN drugstock_drugndc ON drugname.drugnameid_PK = drugstock_drugndc.drugnameid_FK
INNER JOIN drugndc ON drugstock_drugndc.drugndcid_FK = drugndc.drugid_PK
LEFT JOIN clinic ON drugstock_drugname.clinicid_FK = clinic.clinicid_PK

WHERE   (@ClinicId = 0 AND 1 = 1)
    OR  (@ClinicId != 0 AND drugstock_drugname.clinicid_FK = @ClinicId)

    -- Alternative Case When You can use OR
    AND ((@selecttype = 1 AND 1 = 1)
    OR  (@selecttype = 2 AND drugname.drugnameid_PK = @selectedValue)
    OR  (@selecttype = 3 AND drugndc.drugid_PK = @selectedValue)
    OR  (@selecttype = 4 AND drugname.cdrugclass = 'C2')
    OR  (@selecttype = 5 AND LEFT(drugname.cdrugclass, 1) = 'C'))

ORDER BY clinic.cclinicname, drugname.cdrugname
END


답변

이 쿼리를 시도하십시오. 위의 게시물에 답변 :

select @msgID, account_id
    from viewMailAccountsHeirachy
    where
    CASE @smartLocationType
        WHEN 'store' THEN account_location
        WHEN 'area' THEN xxx_location_area
        WHEN 'division' THEN xxx_location_division
        WHEN 'company' THEN xxx_location_company
    END  = @smartLocation