【问题标题】:Transact-SQL stored procedure with conditional "AND" logic具有条件“AND”逻辑的 Transact-SQL 存储过程
【发布时间】:2014-05-08 20:09:11
【问题描述】:

我正在开发一个存储过程,该过程用于根据用户输入的条件过滤网格。在可能的标准中,他们可能会选择查看在某个开始日期和结束日期之间完成的交易。我将 4 个输入参数传递给 proc - @ClientKey,客户端请求信息,@FilterBy(这是从 ASP.NET 的下拉列表中选择的值,基本上告诉 proc 用户是否选择按名称过滤,地址、日期等。在这种情况下,日期的@FilterBy 值为 5)、@Value1,在这种情况下是开始日期,@Value2 在这种情况下是结束日期。

在伪代码中,我想要的是:

选择 ABunchOfColumns FROM SomeJoinedTables WHERE SomeCriteria 和案例@FilterBy WHEN 5 THEN d.TransactionTime >= CAST(@Value1 AS Date) AND d.TransactionTime

以下是完整的查询。我希望比我更精通 SQL 的人能够理清我正在尝试做的事情并提供解决方案。

提前致谢!

@ClientKey  int,
@FilterBy   int,
@Value1 varchar(150),
@Value2 varchar(150)

作为 开始

SELECT d.pKey AS PaymentKey, d.CaseKey, d.InvoiceID, d.AuthorizationCode, d.TransactionID, d.PaymentType, d.Amount, d.ExpirationDate, d.CardType, d.BankName, d.AccountNumber, 
    d.AccountType, c.Name, c.Address1, c.City, c.State, c.Zip, cs.PAmount, cs.TranCode, cs.TranDate, cs.[Desc] AS PaymentDescription, cc.[Desc] AS ChargeCodeDescription,
    d.TransactionTime, a.Name AS AssociationName, d.PaymentType, c.ClientPaymentID
FROM DebtorPayment d INNER JOIN Cases c
    ON d.CaseKey = c.pKey
    AND d.ClientKey = c.ClientKey
INNER JOIN CaseSumm cs
    ON d.CaseKey = cs.CaseKey
    AND d.pKey = cs.Batch
    AND d.ClientKey = cs.ClientKey
INNER JOIN ChargeCodes cc
    ON c.ClientKey = cc.ClientKey
    AND cs.TranCode = cc.RefNum
INNER JOIN AssnCtrl a
    ON c.AssnKey = a.pKey
WHERE c.ClientKey = @ClientKey
AND d.AmountAllocated > 0
AND d.TransactionStatus = 'Successful' 
AND c.Address1 LIKE CASE
    WHEN @FilterBy = 1 THEN '%' + @Value1 + '%'
    ELSE c.Address1
    END
AND d.Amount = CASE
    WHEN @FilterBy = 2 THEN @Value1
    ELSE d.Amount
    END  
AND a.pKey = CASE
    WHEN @FilterBy = 3 THEN CAST(@Value1 AS INT)
    ELSE a.pKey
    END
AND c.ClientPaymentID = CASE
    WHEN @FilterBy = 4 THEN @Value1
    ELSE c.ClientPaymentID
    END 
<ProblemArea>
AND CASE @FilterBy
        WHEN 5 THEN d.TransactionTime >= CAST(@Value1 AS Date) AND d.TransactionTime <= CAST(@Value2 AS Date)
    END
</ProblemArea>
AND c.LName LIKE CASE
    WHEN @FilterBy = 6 THEN '%' + @Value1 + '%'
    ELSE c.LName
    END
ORDER BY d.TransactionTime DESC

结束

【问题讨论】:

    标签: sql sql-server tsql stored-procedures


    【解决方案1】:
    CASE 
        WHEN @FilterBy = 5 AND d.TransactionTime >= CAST(@Value1 AS DATE) 
        AND d.TransactionTime <= CAST(@Value2 AS DATE) THEN 1 
        ELSE 0 
    END = 1
    

    【讨论】:

    • or.. CASE WHEN @FilterBy = 5 AND d.TransactionTime BETWEEN CAST(@Value1 AS DATE) AND CAST(@Value2 AS DATE) THEN 1 ELSE 0 END = 1 工作方式相同,但between 使代码更具可读性。那只是个人喜好,执行上没有区别。
    • 其实我只是在完成另一个系统增强之前简单地测试了这个。现在我回到了这个问题上,似乎 proc 没有返回除 5 以外的任何行和 @FilterBy 值。不知道为什么。
    • 对于任何除 5 以外的 @FilterBy 值。
    • @Mike 我只关注您所在位置的“问题区域”部分。看来您需要使用AND ((First @FilterBy) OR (Second @FilterBy) OR ....)。无论如何,我没有审查所有这些过滤器
    • 感谢 Lamak - 了解重点范围。还没有快乐,但仍在努力。
    【解决方案2】:

    你的意思是像下面这样吗? 您可能会发现这个link 也很有用。 没有测试过代码,只是提出想法——写这样的代码对我来说一直觉得“错误”——也许有人可以提供更好的。

    CREATE PROC MyProc
    
        @ClientKey  int,
        @FilterBy   int,
        @Value1 varchar(150),
        @Value2 varchar(150)
    --  NB WITH RECOMPILE, see link (above)
    WITH RECOMPILE AS
    BEGIN
        SET NOCOUNT ON;
    
        SELECT *
        FROM ...
        WHERE 
            Col1    =   CASE 
                            WHEN @FilterBy = 1 THEN @Value1
                            ELSE Col1
                        END
        AND
            1       =   CASE
                            WHEN @FilterBy = 2 AND Col2 > @Value1 AND Col3 < @Value2        THEN 1
                            WHEN @FilterBy = 2 AND NOT (Col2 > @Value1 AND Col3 < @Value2)  THEN 0
                            ELSE 1
                        END 
    END
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-02
      • 2011-11-04
      • 2011-05-28
      相关资源
      最近更新 更多