【问题标题】:CASE in WHERE clause in T-SQLT-SQL 中 WHERE 子句中的 CASE
【发布时间】:2018-12-20 03:58:00
【问题描述】:

尝试使用CASE作为条件参数

我之前已经发过这个了;但由于我无法获得正确的结果,所以用不同的方法再次发布。

我有一个复杂的代码,我只添加了几个元素,以黄色突出显示

我的目标是:

  • 当@Depreciation = 0
    需要显示值 - 没有“折旧”(其中 DepreciationAcc =0)

  • 当@Depreciation = 1
    需要显示值 - 使用“折旧”(其中 DepreciationAcc 为 0 或 1)

它可以工作,但选择的行数不正确。

这是我在 WHERE 中使用 CASE 的部分:

 WHERE ( 
  (CASE WHEN (NOT (acct.[GLAccountCode] IN (N'9040',N'9047',N'4130')) AND 
  (@Depreciation = 0))THEN 0 ELSE trans.Amount END)=0 .............

以下是完整代码。我正在尝试修改的部分 - 用 /****/ 标记:(主要在第一个 WHERE 之后)

DECLARE @FYMonthBOP date = '2017-07-01'
DECLARE @FYMonthEOP date = '2018-03-31'
DECLARE @GLProgramGroupsWHID int = -1
DECLARE @GLProgramsWHID_Groups int = -1
DECLARE @GLProgramGroupSetsWHID int = -1
DECLARE @Depreciation bit = 1          /****/

SELECT        
  gl0.GLGroupLevel0Name
, gl0.Ordinal AS Ordinal0
, [Dimension].GLGroupLevel1.GLGroupLevel1Name
, [Dimension].GLGroupLevel1.Ordinal AS Ordinal1
, gl2.GLGroupLevel2Name
, gl2.Ordinal AS Ordinal2
, acct.GLAccountCode
, acct.GLAccountName
         , pgm.GLProgramCode + N' ' + pgm.GLProgramName AS Program
, setname.[WHID] AS [WHIDGroupSetName]
         , grp.GroupName 
, grp.WHID AS WHIDGroupName
, grp.Ordinal AS OrdinalGroupName
, d.FYQuarterLabel AS FQ
 -- , trans.Amount AS Amount
 -- , CASE WHEN     ((acct.[GLAccountCode] IN (N'9040',N'9047',N'4130')) 
  AND (@Depreciation = 0)) THEN 0 ELSE trans.Amount END AS [Amount] 
, pgm.[WHID] AS WHIDProgram
, pgm.Ordinal AS OrdinalProgram
, d.FYMonthNumber
, d.FYMonthShortLabel
, d.FYQuarterNumber
, d.FYNumber
, d.FYLabel
, d.YearMonthSort
, IIF(EOMonth(mm.DateThru) < @FYMonthEOP, EOMonth(mm.DateThru), 
       @FYMonthEOP) AS [DateThru]
, IIF((acct.[GLAccountCode]) IN (N'9040',N'9047',N'4130'), 1, 0) AS 
      [DepreciationAcct]

 FROM            
(([Dimension].GLGroupLevel2 gl2 WITH (NoLock)
INNER JOIN [Dimension].GLAccount acct WITH (NoLock) ON gl2.[WHID] = 
                                     acct.GLGroupLevel2FK 
INNER JOIN [Dimension].GLGroupLevel0 gl0 WITH (NoLock)
INNER JOIN [Dimension].GLGroupLevel1 WITH (NoLock) ON gl0.[WHID] = 
               [Dimension].GLGroupLevel1.GLGroupLevel0FK ON    
               GLGroupLevel1FK = [Dimension].GLGroupLevel1.[WHID] 
INNER JOIN Fact.GLTransactionsMonthly trans WITH (NoLock) ON acct. 
                   [WHID] = trans.GLAccountFK 
INNER JOIN [Dimension].GLProgram pgm WITH (NoLock) ON trans. 
               [GLProgramFK] = pgm.[WHID] AND trans.[GLProgramFK] = 
               pgm.[WHID] AND trans.[GLProgramFK] = pgm.[WHID] 
INNER JOIN [Dimension].[Date] d WITH (NoLock) ON trans.EffectiveMonth = 
               d.[Date] AND trans.EffectiveMonth = d.[Date] 

                AND trans.EffectiveMonth = d.[Date] 
INNER JOIN [Reports].GLProgramGroupMapping map ON map.GLProgramFK = 
                         pgm.[WHID]
INNER JOIN [Reports].GLProgramGroup grp ON grp.WHID = 
                         map.GLProgramGroupFK
INNER JOIN [Reports].GLProgramGroupSet setname ON setname.WHID = 
                         grp.GLProgramGroupSetFK))

CROSS APPLY (
    SELECT MAX(t.EffectiveMonth) AS [DateThru] 
    FROM Fact.GLTransactionsMonthly t WITH (NoLock) 
) mm

  WHERE ( 
     (CASE WHEN (NOT (acct.[GLAccountCode] IN (N'9040',N'9047',N'4130')) 
                 AND (@Depreciation = 0)) 
            THEN 0 ELSE trans.Amount END)=0 AND    /****/

     (trans.EffectiveMonth BETWEEN @FYMonthBOP AND @FYMonthEOP)
AND ((setname.WHID IN (@GLProgramGroupSetsWHID)) OR (-1 IN 
         (@GLProgramGroupSetsWHID)))
AND ((grp.WHID IN (@GLProgramGroupsWHID)) OR (-1 IN 
         (@GLProgramGroupsWHID)))
AND ((pgm.[WHID] IN (@GLProgramsWHID_Groups)) OR (-1 IN 
         (@GLProgramsWHID_Groups)))

AND (
    (pgm.[WHID] IN (
    SELECT DISTINCT      
         f.[GLProgramFK]

    FROM            
        Fact.GLTransactionsMonthly f
        INNER JOIN [Dimension].[GLAccount] acct ON f. 
                    [GLAccountFK] = acct.[WHID]

    WHERE 
        (f.EffectiveMonth BETWEEN @FYMonthBOP AND @FYMonthEOP)
        AND (acct.[GLAccountCode] BETWEEN '5000' AND '9999')

    GROUP BY
         f.[GLProgramFK]

    HAVING 
        (SUM(f.[Amount]) <> 0))
    )
OR
    (pgm.[WHID] IN (
    SELECT DISTINCT      
         f.[GLProgramFK]

    FROM            
        Fact.GLTransactionsMonthly f
        INNER JOIN [Dimension].[GLAccount] acct ON f. 
                    [GLAccountFK] = acct.[WHID]

    WHERE 
        (f.EffectiveMonth BETWEEN @FYMonthBOP AND @FYMonthEOP)
        AND (acct.[GLAccountCode] BETWEEN '4000' AND '4999')

    GROUP BY
         f.[GLProgramFK]

    HAVING 
        (SUM(f.[Amount]) <> 0))
    )
OR 
    (pgm.[GLProgramCode] IN ('549'))

)   
    )

【问题讨论】:

    标签: sql-server function tsql parameters


    【解决方案1】:

    最近才了解到解决我的问题的正确方法 -

    CASE WHEN   (acct.[GLAccountCode] IN (N'9040',N'9047',N'4130')) AND 
                (@Depreciation = 0) THEN 0 ELSE 1 END)=1
    

    不需要包含trans.Amount字段,且值必须等于1,而不是0 这样它将显示所有值

    【讨论】:

      【解决方案2】:

      考虑谓词的基本结构:

      (CASE 
          WHEN ... AND @Depreciation = 0 THEN 0 
          ELSE trans.Amount END 
      ) = 0
      

      从 case 表达式中出来的所有内容都由 equal 0 求值,因此如果 trans.Amount &lt;&gt; 0 则它不会在结果中存活

      编辑

      我想你可能想要这个:

      WHERE ( 
               (@Depreciation = 0 and  [DepreciationAcct] = 0)
             OR
               (@Depreciation = 1 and  [DepreciationAcct] IN (0,1))
            )
      

      【讨论】:

      • 是的,你是对的 - 我刚刚注意到并检查了 - 关于你提到的 - 当 Depreciation = 1 时,它只显示 trans.Amount = 0 的行(1935 行)我的问题是 - 如何是否显示 @Depreciation = 1 的所有剩余值?
      • 好吧,也许您可​​以重新考虑如何提出技术问题。您可以提供一个很小的数据示例(称为“样本数据”)和您想要从该数据中获得的结果(称为“预期结果”),而不是重新列出与您的需求不匹配的冗长查询作为您的问题。这在stackoverflow中被称为MCVE,使用这些有很好的理由,请参阅Why should I provide a MCVE
      • 除此之外,在我看来,您可能不需要 where 子句中的任何逻辑,而您可能只需要 select 子句中的逻辑,但老实说,我只是不需要真正了解你真正想要什么(问题不清楚)。
      • @ Used_By_Already,抱歉,谢谢,我会进行编辑 我想要的(我的目标)如下:当折旧 = 0 时,我只想查看字段 [DepreciationAcct] 的行= 0(这是上面代码中我的 IIF 语句中的字段)当 Depreciation = 1 我想查看 [DepreciationAcct] = 1 或 [DepreciationAcct] = 0 的行 - 这两个值
      • @ Used_By_Already 谢谢,但是......不幸的是,字段 [DepreciationAcct] 是以下 IIF 语句的一部分 - IIF((acct.[GLAccountCode]) IN (N'9040',N'9047 ',N'4130'), 1, 0) AS [DepreciationAcct] 并且不能用作条件的独立部分。我的仓库根本不认识它
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-26
      • 2021-08-09
      • 1970-01-01
      相关资源
      最近更新 更多