【问题标题】:How to set a specific condition to a new Parameter in T-SQL如何在 T-SQL 中为新参数设置特定条件
【发布时间】:2018-12-13 02:56:39
【问题描述】:

我有一个现有代码,我必须向其中添加新参数 - @Depreciation“是”或“否”

如果@Depreciation = 1(我认为这对应于“是”) 那么我希望现有代码的特定条件是 FALSE(我用 '-- ***' 标记了该代码部分),

反之亦然 -

如果@Depreciation = 0('否') 那么我希望代码中的条件是 是的

条件是

 (NOT (acct.[GLAccountCode] IN (N'9040',N'9047',N'4130')))

位于下面代码中的第一个 WHERE 之后。

请不要过多关注整个代码。 我必须修改的唯一部分是 - 'DECLARE @Depreciation....' 和 在第一个 'WHERE .....' 之后 - 我标记了 -- ***

     DECLARE @FYMonthBOP date = '07-01-2016'
     DECLARE @FYMonthEOP date = '07-01-2018'
     DECLARE @GLProgramGroupsWHID int = -1
     DECLARE @GLProgramsWHID_Groups int = -1
     DECLARE @GLProgramGroupSetsWHID int = -1

     DECLARE @Depreciation bit = 1 -- *** This is my added Parameter

    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
     , setname.WHID AS WHIDGroupSetName
     , setname.GroupSetName
     , pgm.GLProgramCode + N' ' + pgm.GLProgramName AS Program
     , grp.GroupName
     , grp.WHID AS WHIDGroupName
     , grp.Ordinal AS OrdinalGroupName 
     , d.FYQuarterLabel AS FQ
     , trans.Amount 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]

 FROM            
       ([Dimension].GLGroupLevel2 gl2
      INNER JOIN [Dimension].GLAccount acct ON gl2.[WHID] = 
                                               acct.GLGroupLevel2FK 
      INNER JOIN [Dimension].GLGroupLevel0 gl0
      INNER JOIN [Dimension].GLGroupLevel1 ON gl0.[WHID] = 
                 [Dimension].GLGroupLevel1.GLGroupLevel0FK ON 
                             gl2.GLGroupLevel1FK = 
                             [Dimension].GLGroupLevel1.[WHID] 
      INNER JOIN Fact.GLTransactionsMonthly trans ON acct.[WHID] = 
                                            trans.GLAccountFK 
      INNER JOIN [Dimension].GLProgram pgm ON trans.[GLProgramFK] = 
                 pgm.[WHID] AND trans.[GLProgramFK] = 
                 pgm.[WHID] AND trans.[GLProgramFK] = pgm.[WHID] 
      INNER JOIN [Dimension].[Date] d ON trans.EffectiveMonth = d.[Date] 
                 AND trans.EffectiveMonth = d.[Date] 
                 AND trans.EffectiveMonth = d.[Date] 
      INNER JOIN [Dimension].GLRegion ON pgm.GLRegionFK = 
                 [Dimension].GLRegion.[WHID] AND pgm.GLRegionFK = 
                 [Dimension].GLRegion.[WHID]
      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


-- *** This, below -    

WHERE (
 (NOT (acct.[GLAccountCode] IN (N'9040',N'9047',N'4130'))) 

-- *** is the condition I want to execute, if my Parameter = False, and not 
-- *** to execute, if my Parameter = True  


   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 (NOT (acct.[GLAccountCode] IN (N'9040',N'9047'))) 
            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 (NOT (acct.[GLAccountCode] IN (N'4130'))) 
                     AND (acct.[GLAccountCode] BETWEEN '4000' AND '4999') 

                         GROUP BY
                               f.[GLProgramFK]

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

【问题讨论】:

    标签: sql-server tsql reporting-services parameters


    【解决方案1】:

    像这样:

    (
      (
        @Depreciation = 0 /* FALSE AND EXISTING CONDITION */
        and NOT (acct.[GLAccountCode] IN (N'9040',N'9047',N'4130'))
      )
      or
      (
        @Depreciation = 1 /* OR TRUE AND NOT EXISTING CONDITION */
        and (acct.[GLAccountCode] IN (N'9040',N'9047',N'4130'))
      )
    )
    

    【讨论】:

    • 您有一个非常复杂的查询 - 添加OR 条件经常会减慢速度。一个快速的解决方案可以是 union all 每个条件,即为 OR 条件的每个分支创建 2 个查询,然后将所有查询合并在一起。虽然没有任何承诺,正如我所说的那样,这是一个非常复杂的查询 - 我个人可能会分解它。
    • 这是您使用@Depreciation 参数的方式...优化器必须在知道@Depreciation 的值之前提出一个执行计划。因此,它选择了一个“安全”的扫描操作,对任何一个值都有效(很差)。尝试在查询末尾添加OPTION(RECOMPILE)OPTION(RECOMPILE)将导致优化器在它具有参数值之后重新编译一个新计划,并将创建一个专门针对该组参数值优化的计划。
    • 其实执行慢的问题是因为我习惯了其他参数的间隔比较大。这不再是问题,它工作得很快!但是我的预期数据量仍然不匹配(当我比较原始查询时)正如我所见,这是因为查询太复杂了,我需要修改的地方很少......!!!谢谢大家
    猜你喜欢
    • 2023-03-11
    • 1970-01-01
    • 1970-01-01
    • 2011-06-06
    • 2020-04-21
    • 2017-05-25
    • 1970-01-01
    • 1970-01-01
    • 2011-07-06
    相关资源
    最近更新 更多