Sql server SQL-Where子句中的Case以减少IF语句

Sql server SQL-Where子句中的Case以减少IF语句,sql-server,tsql,Sql Server,Tsql,尝试执行时出错。我不是DBA,但我需要根据传入的变量在where子句中进行筛选。我使用了一个包含IF语句的大型语句,但看起来很糟糕,所以我想出了这个主意,但却出现了错误 查询: DECLARE @VariableName AS NVARCHAR(100), @VariableValue AS NVARCHAR(MAX), @PileFrom AS INT, @PileTo AS INT, @BeginDate AS DATETIME, @E

尝试执行时出错。我不是DBA,但我需要根据传入的变量在where子句中进行筛选。我使用了一个包含IF语句的大型语句,但看起来很糟糕,所以我想出了这个主意,但却出现了错误

查询:

    DECLARE
    @VariableName AS NVARCHAR(100),
    @VariableValue AS NVARCHAR(MAX),
    @PileFrom AS INT,
    @PileTo AS INT,
    @BeginDate AS DATETIME,
    @EndDate AS DATETIME,
    @Truck AS BIT,
    @Train AS BIT
--AS
BEGIN
    IF @BeginDate = '' BEGIN
        SET @Begindate = '1/1/1900'
    END

    IF @EndDate = '' BEGIN
        SET @EndDate = '1/1/9999'
    END 

    IF @Truck = 1 BEGIN
        SELECT 
            Car_ID,
            PO_Number,
            Vendor,
            Shipper,
            Commodity,
            Date_Weighed_In,
            Date_Weighed_Out,
            Pile_No AS 'PILe From',
            Pile_No1 AS 'Pile To',
            Operator_In,
            Operator_Out,
            Comments_In,
            Comments_Out,
            Weight_In,
            Weight_Out,
            Transaction_Num,
            Record_time_Stamp
        FROM
            dbo.Transactions_Truck
        WHERE
            (Date_Weighed_IN BETWEEN @BeginDate AND @EndDate) AND
            CASE 
                WHEN @VariableName = 'rbCardID'         THEN Car_ID = @VariableValue
                WHEN @VariableName = 'rbPONumber'       THEN PO_Number = @VariableValue
                WHEN @VariableName = 'rbVendor'         THEN Vendor = @VariableValue
                WHEN @VariableName = 'rbCommodity'      THEN Commodity = @VariableValue
                WHEN @VariableName = 'rbPileNumber'     THEN Pile_No = @PileFrom AND Pile_No1 = @PileTo
                WHEN @VariableName = 'rbTransactionNum' THEN Transaction_Num = @VariableValue
                WHEN @VariableName = 'rbOperator'       THEN Operator_In = @VariableValue
                WHEN @VariableName = 'rbComments'       THEN Comments_In = @VariableValue           
        END ELSE IF @Train = 1 BEGIN
            SELECT 
                Car_ID,
                PO_Number,
                Vendor,
                Shipper,
                Commodity,
                Date_Weighed_In,
                Date_Weighed_Out,
                Pile_No AS 'PILe From',
                Pile_No1 AS 'Pile To',
                Operator_In,
                Operator_Out,
                Comments_In,
                Comments_Out,
                Weight_In,
                Weight_Out,
                Transaction_Num,
                Record_time_Stamp
            FROM
                dbo.Transactions_train
            WHERE
                (Date_Weighed_IN BETWEEN @BeginDate AND @EndDate) AND
                CASE 
                    WHEN @VariableName = 'rbCardID'         THEN Car_Id = @VariableValue
                    WHEN @VariableName = 'rbPONumber'       THEN PO_Number = @VariableValue
                    WHEN @VariableName = 'rbVendor'         THEN Vendor = @VariableValue
                    WHEN @VariableName = 'rbCommodity'      THEN Commodity = @VariableValue
                    WHEN @VariableName = 'rbPileNumber'     THEN Pile_No = @PileFrom AND Pile_No1 = @PileTo
                    WHEN @VariableName = 'rbTransactionNum' THEN Transaction_Num = @VariableValue
                    WHEN @VariableName = 'rbOperator'       THEN Operator_In = @VariableValue
                    WHEN @VariableName = 'rbComments'       THEN Comments_In = @VariableValue
                    WHEN @VariableName = 'rbRailRoad'       THEN Rail_Road = @VariableValue
        END
END

你不能那样做你的where声明。。你应该使用AND和OR

WHERE   (Date_Weighed_IN BETWEEN @BeginDate AND @EndDate)
        AND (
                (@VariableName = 'rbCardID'         AND Car_Id          = @VariableValue)
            OR  (@VariableName = 'rbPONumber'       AND PO_Number       = @VariableValue)
            OR  (@VariableName = 'rbVendor'         AND Vendor          = @VariableValue)
            OR  (@VariableName = 'rbCommodity'      AND Commodity       = @VariableValue)
            OR  (@VariableName = 'rbPileNumber'     AND Pile_No         = @PileFrom         
                                                    AND Pile_No1        = @PileTo       )
            OR  (@VariableName = 'rbTransactionNum' AND Transaction_Num = @VariableValue)
            OR  (@VariableName = 'rbOperator'       AND Operator_In     = @VariableValue)
            OR  (@VariableName = 'rbComments'       AND Comments_In     = @VariableValue)
            OR  (@VariableName = 'rbRailRoad'       AND Rail_Road       = @VariableValue)
        )

你不能那样做你的where声明。。你应该使用AND和OR

WHERE   (Date_Weighed_IN BETWEEN @BeginDate AND @EndDate)
        AND (
                (@VariableName = 'rbCardID'         AND Car_Id          = @VariableValue)
            OR  (@VariableName = 'rbPONumber'       AND PO_Number       = @VariableValue)
            OR  (@VariableName = 'rbVendor'         AND Vendor          = @VariableValue)
            OR  (@VariableName = 'rbCommodity'      AND Commodity       = @VariableValue)
            OR  (@VariableName = 'rbPileNumber'     AND Pile_No         = @PileFrom         
                                                    AND Pile_No1        = @PileTo       )
            OR  (@VariableName = 'rbTransactionNum' AND Transaction_Num = @VariableValue)
            OR  (@VariableName = 'rbOperator'       AND Operator_In     = @VariableValue)
            OR  (@VariableName = 'rbComments'       AND Comments_In     = @VariableValue)
            OR  (@VariableName = 'rbRailRoad'       AND Rail_Road       = @VariableValue)
        )

<代码> JAMIDE77 的答案应该做这项工作,但是很多OR可能会让你陷入性能问题,所以我也会考虑使用<代码>动态SQL 来尝试执行一个更小的SQL语句(这是未经测试的,我已经重新格式化以使其更可读):

这样,您的代码就更多了,我认为您应该更快(我不知道引擎是否知道优化所有这些ORs,这可能比使用动态查询可能会损失的性能还要糟糕)

更好的方法是以类型化的方式进行比较。与
@VariableValue
相比,我无法看到所有列的数据类型,但我假设ID和日期不是字符串。如果类型不同于
NVARCHAR
,则将为每个不匹配的类型生成隐式强制转换,性能将降低


然而,这将需要使用实体框架(如果这就是您的过程所做的,并且是一个很好的练习的话,这应该不难)或类似的东西来完全重写您的逻辑

>代码> JAMIDE77 的答案应该做这项工作,但是许多OR可能会使你陷入性能问题,所以我也会考虑使用<代码>动态SQL 试图获得一个更小的SQL语句,执行(这是未测试的,我已经重新格式化以使其更可读):

这样,您的代码就更多了,我认为您应该更快(我不知道引擎是否知道优化所有这些ORs,这可能比使用动态查询可能会损失的性能还要糟糕)

更好的方法是以类型化的方式进行比较。与
@VariableValue
相比,我无法看到所有列的数据类型,但我假设ID和日期不是字符串。如果类型不同于
NVARCHAR
,则将为每个不匹配的类型生成隐式强制转换,性能将降低


然而,这将需要使用实体框架(如果这就是您的过程所做的,并且是一个很好的练习的话,这应该不难)或类似的东西来完全重写您的逻辑

有关于这些错误是什么的提示吗?我讨厌猜谜游戏。你的案例中有
END
吗?你的
@BeginDate
@EndDate
变量是日期时间,所以你可能应该将它们与NULL进行比较,而不是“”,因为日期不能是空字符串。关于这些错误是什么的提示?我讨厌猜谜游戏。你的案例中有
END
吗?你的
@BeginDate
@EndDate
变量都是日期时间,所以你可能应该将它们与NULL进行比较,而不是“”,因为日期不能是一个空字符串,它在几分钟内看起来很糟糕,在几分钟内看起来很糟糕,真的很像动态SQL,请不要误会,但我听说这并不是最佳实践。我尽量让事情变得简单,让后面来的人知道。因此,如果这是一个个人项目,我会完全使用动态SQL,但这是一个公司项目。感谢您提供的动态示例,它非常有帮助,也感谢您提供的其他解决方案。不重复的内容更易于理解和维护。任何看到代码的人都会问(至少我问过)@Train=0或1之间的区别是什么,因为代码几乎相同。不推荐使用动态SQL,因为它很有用,但在某些情况下可能很好。包含许多或多个条件的大型查询更难通过引擎进行优化(也更难被人类理解)。我非常喜欢动态SQL,请不要误解我的意思,但我听说它不是最佳实践。我尽量让事情变得简单,让后面来的人知道。因此,如果这是一个个人项目,我会完全使用动态SQL,但这是一个公司项目。感谢您提供的动态示例,它非常有帮助,也感谢您提供的其他解决方案。不重复的内容更易于理解和维护。任何看到代码的人都会问(至少我问过)@Train=0或1之间的区别是什么,因为代码几乎相同。不推荐使用动态SQL,因为它很有用,但在某些情况下可能很好。包含许多或多个条件的大型查询更难通过引擎进行优化(也更难被人类理解)。