根据参数值

时间:2019-02-08 10:31:01

标签: sql sql-server stored-procedures

我有2个存储过程,它们返回与我尝试合并到单个过程中相同的列。它们都有一组不同的参数,并且都有不同的WHERE子句,但是它们使用相同的表并选择完全相同的行。

WHERE子句1 :(使用@UIOID和@Level)

WHERE   (   @UIOID = CASE   WHEN @Level = 'Single' THEN C.C_UIOID_PK        
                WHEN @Level = 'Children' THEN CLC.UIOL_P
                WHEN @Level = 'Parent' THEN CLP.UIOL_C
            END 
        OR  (   @UIOID = '0'    
            AND @Level = 'All'          
            )
            )

第2条:(使用@ TeamCode,@ Year,@ IncludeQCodes)

WHERE   C.C_IsChild = 0
AND C.C_MOA <> 'ADD'
AND @TeamCode = C.C_OffOrg
AND C.C_Active = 'Y'
AND (   @Year BETWEEN dbo.f_GetAcYearByDate(C.C_StartDate) AND dbo.f_GetAcYearByDate(C.C_EndDate)
        OR @Year = 0    )
AND (   C.C_InstCode NOT LIKE 'Q%'
        OR  @IncludeQCodes = 1    )   

理想情况下,我想添加一个新参数,该参数基本上告诉它要运行的两个WHERE子句中的哪一个,但是我似乎无法使用CASE语句重新创建该参数,因为据我所知,它们仅适用于单个WHERE子句,不是一整套不同的子句

我想这样做,而不必再次重复执行select语句并将整个内容放入IF语句中,而且我也不想将查询放入字符串中。我只想要一个选择语句。

使用临时表的问题是查询本身需要一段时间才能运行,并且没有任何参数,并且在实时网站中使用,因此我不希望它必须将所有记录放入临时表中然后进行过滤

使用CTE的问题是您不能将其与IF语句一起使用,因此也无法使用。

这是我要实现的逻辑:

SELECT  A
        B
        C    
FROM    X
IF @WhichOption = 1 THEN
    WHERE   (   @UIOID = CASE   WHEN @Level = 'Single' THEN C.C_UIOID_PK        
                WHEN @Level = 'Children' THEN CLC.UIOL_P
                WHEN @Level = 'Parent' THEN CLP.UIOL_C
            END 
        OR  (   @UIOID = '0'    
            AND @Level = 'All'          
            )
        )
ELSE IF @WhichOption = 2 THEN 
    WHERE   C.C_IsChild = 0
    AND C.C_MOA <> 'ADD'
    AND @TeamCode = C.C_OffOrg
    AND C.C_Active = 'Y'
    AND (   @Year BETWEEN dbo.f_GetAcYearByDate(C.C_StartDate) AND     dbo.f_GetAcYearByDate(C.C_EndDate)
                OR @Year = 0    )
    AND (   C.C_InstCode NOT LIKE 'Q%'
            OR  @IncludeQCodes = 1  )  

3 个答案:

答案 0 :(得分:0)

尝试使用动态SQL:

DECLARE @sql NVARCHAR(max), @where NVARCHAR(max), @WhichOption INT = 1;

SET @sql = 'SELECT  A
        B
        C    
FROM    X';

IF @WhichOption = 1
    SET @where = 'WHERE   (   @UIOID = CASE   WHEN @Level = ''Single'' THEN C.C_UIOID_PK        
                WHEN @Level = ''Children'' THEN CLC.UIOL_P
                WHEN @Level = ''Parent'' THEN CLP.UIOL_C
            END 
        OR  (   @UIOID = ''0''    
            AND @Level = ''All''
            )
        )';
ELSE IF @WhichOption = 2 
    SET @where = ' WHERE   C.C_IsChild = 0
    AND C.C_MOA <> ''ADD''
    AND @TeamCode = C.C_OffOrg
    AND C.C_Active = ''Y''
    AND (   @Year BETWEEN dbo.f_GetAcYearByDate(C.C_StartDate) 
        AND dbo.f_GetAcYearByDate(C.C_EndDate)
                OR @Year = 0    )
    AND (   C.C_InstCode NOT LIKE ''Q%''
            OR  @IncludeQCodes = 1  ) ';

SET @sql = CONCAT(@sql,' ',  @where)
PRINT @sql
EXECUTE sp_executesql @sql

答案 1 :(得分:0)

在过程中保存以下过程。您也可以直接插入物理表中。

declare @varTable Table (columns exactly as Procedures return)

if(condition is met)
  begin 
       insert into @varTable
       exec proc1
  end 
else 
  begin 
       insert into @varTable
       exec proc2
  end

答案 2 :(得分:0)

添加您说的参数,该参数将指示适用什么过滤器:

select XXXXX
from XXXXX
where (@Mode = 1 and ( filter 1 ))
      or
      (@Mode = 2 and ( filter 2 ))  

option(recompile) 

如果@Mode参数为1,则它将评估过滤器1,否则它将评估过滤器2。

在语句的末尾添加 option(recompile),因此SQL引擎将用变量的值替换变量,消除将不被评估的过滤器,并生成执行工厂只是要应用的过滤器。

PS:请注意,尽管这些综合查询非常易于编码和维护,并且能够生成完美的功能和最佳执行,但不建议将其用于高要求的应用程序。选项(recompile)强制引擎在每次执行时重新编译并生成一个新的执行计划,如果您的查询需要每分钟执行数百次,那么这会对性能产生显着影响。但是对于偶尔使用,这是完全可以的。