如何在带参数的存储过程中的位置之间的条件之间选择“ AND”或“ OR”?

时间:2019-07-15 05:19:45

标签: sql sql-server tsql

我有一个存储过程来返回由某些参数过滤的结果(所有参数都是可选的)。

有时候我想得到条件1和条件2为真的结果,有时是当只有一个条件为真时的结果。

SELECT 
    *
FROM
    ProductAndServices
WHERE
    Title       = ISNULL(@Title,Title)         @AndOR 
    CreatedBy   = ISNULL(@CreatedBy,CreatedBy)  

5 个答案:

答案 0 :(得分:2)

您可以引入一个变量/参数,该变量/参数指定是否要对字段使用AND或OR逻辑,并将该参数也包含在WHERE子句中。

例如这样的东西:

-- Declared a variable here, but might be a stored procedure parameter as well
DECLARE @And BIT = 1 -- When 0, WHERE uses OR; when 1, WHERE uses AND

SELECT 
    *
FROM
    ProductAndServices
WHERE
    (@And = 0 AND (Title = ISNULL(@Title, Title) OR  CreatedBy = ISNULL(@CreatedBy, CreatedBy))) OR
    (@And = 1 AND (Title = ISNULL(@Title, Title) AND CreatedBy = ISNULL(@CreatedBy, CreatedBy)))
OPTION (RECOMPILE)

此外,我会避免在WHERE子句中使用ISNULL之类的函数,因为它可能会阻止查询优化器使用索引。

所以代替这个:

Title = ISNULL(@Title, Title)
CreatedBy = ISNULL(@CreatedBy, CreatedBy)

我会使用:

(@Title IS NULL OR Title = @Title)
(@CreatedBy IS NULL OR CreatedBy = @CreatedBy)

这样,查询将变为:

SELECT 
    *
FROM
    ProductAndServices
WHERE
    (@And = 0 AND ((@Title IS NULL OR Title = @Title) OR  (@CreatedBy IS NULL OR CreatedBy = @CreatedBy))) OR
    (@And = 1 AND ((@Title IS NULL OR Title = @Title) AND (@CreatedBy IS NULL OR CreatedBy = @CreatedBy)))
OPTION (RECOMPILE)

因此,后一个查询更长,并且不如前一个查询可读,但是它应该表现得更好。我认为。我还没有测试。您可能需要使用多个数据集进行基准测试(并检查相应的执行计划),以确保确定。

编辑:

根据Marc Guillot的提示,我向查询中添加了OPTION (RECOMPILE)。您可以查看Microsoft文档中的Query Hints文档,以获取有关它的更多信息。

我还刚刚发现了Improving query performance with OPTION (RECOMPILE), Constant Folding and avoiding Parameter Sniffing issues的文章Robin Lester。尚未完全阅读,但快速扫描后,对我来说似乎是一本好书。

答案 1 :(得分:1)

您可以尝试在例程中构建动态T-SQL语句。编写和调试起来有点困难,但是它将导致更简单的T-SQL语句被执行并从那里执行-可能会提高性能。这是一个示例:

DECLARE @Tittle VARCHAR(12)
       ,@CreatedBy VARCHAR(12)
       ,@AndOR VARCHAR(12)

SELECT @Tittle = 'Here comes the sun'
      ,@CreatedBy = 'Beatles'
      ,@AndOR = 'AND';

SELECT @Tittle = ISNULL(@Tittle, '')
      ,@CreatedBy = ISNULL(@CreatedBy, '')
      ,@AndOR = ISNULL(@AndOR, 'AND');

DECLARE @DynammicTSQLStatement NVARCHAR(MAX);

SET @DynammicTSQLStatement =N'
SELECT 
    *
FROM
    ProductAndServices
WHERE ' + CASE WHEN  @Tittle = '' THEN '' ELSE 'Title = ''' + @Tittle  + '''' END
        + CASE WHEN @Tittle <> '' AND @CreatedBy <> '' THEN ' ' + @AndOR + ' CreatedBy = ''' + @CreatedBy + '''' ELSE '' END;

SELECT  @DynammicTSQLStatement

EXEC sp_executesql @DynammicTSQLStatement;

答案 2 :(得分:0)

为您的案件使用if条件:

    GO

    if (@Condtion)
    Begin
    SELECT * FROM ProductAndServices
    WHERE
        Title       = ISNULL(@Title,Title) And
        CreatedBy   = ISNULL(@CreatedBy,CreatedBy)  

    End
    Else
    Begin
    SELECT * FROM ProductAndServices
    WHERE
        Title       = ISNULL(@Title,Title) OR
        CreatedBy   = ISNULL(@CreatedBy,CreatedBy)  

    End

我确定您想使用sometimes以及何时使用AND的{​​{1}}。

答案 3 :(得分:0)

以下查询应执行您想要的操作

precision highp float;

uniform sampler2D sTexture;
varying vec2 vTexCoordIn;

void main ()
{
    vec2 uv = vTexCoordIn.xy

    if (vTexCoordIn.x >= 0.7 && vTexCoordIn.x <= 0.9)
    {
        vec2  pos     = vTexCoordIn.xy * 2.0 - 1.0;
        float b       = 0.3;
        float v_scale = (1.0 + b) / (1.0 + b * sqrt(1.0 - pos.x*pos.x));

        float u = asin( pos.x ) / 3.1415 + 0.5;
        float v = (pos.y * v_scale) * 0.5 + 0.5;
        if (v >= 0.0 && v <= 1.0)
          uv = vec2(u, v);
    }

    vec3 texColor = texture2D(sTexture, uv).rgb;
    gl_FragColor  = vec4(texColor.rgb, 1.0);
 }

答案 4 :(得分:0)

写为 SQL语句,如下所示

DECLARE @str VARCHAR(max)=N'SELECT *
                               FROM ProductAndServices
                               WHERE  Title='+ CASE WHEN  @Tittle IS NULL THEN 'Title' ELSE '''' + @Tittle  + '''' END
        + ' AND CreatedBy='+ CASE WHEN  @CreatedBy IS NULL THEN 'CreatedBy' ELSE '''' + @CreatedBy  + '''' END

PRINT @str;