【问题标题】:Selecting all data if the string is empty in SQL IN operator如果 SQL IN 运算符中的字符串为空,则选择所有数据
【发布时间】:2020-11-02 00:22:36
【问题描述】:

我的网站中有一个产品过滤器的存储过程,如下所示:

ALTER PROCEDURE [dbo].[sp_product_get_by_filters]
    (@brand_names nvarchar(max),
     @type nvarchar(max))
AS
BEGIN
    SELECT     
        tbl_product.product_code, 
        tbl_product.brand_name, 
        tbl_product.subcategory_code, 
        tbl_product.product_name, 
        tbl_product.product_photo_1,
        tbl_product.filter_code, 
        (select filter_name from tbl_filter where filter_code =  tbl_product.filter_code )as filter_name,
        (select AVG(CAST(rating AS DECIMAL(10,2))) from tbl_review where product_code = tbl_product.product_code) as Rating,
        (select TOP 1 sub_product_price from tbl_sub_product where product_code = tbl_product.product_code) as product_price,
        (select TOP 1 size from tbl_sub_product where product_code = tbl_product.product_code) as size,
        (select TOP 1 sub_product_code from tbl_sub_product where  product_code = tbl_product.product_code) as sub_product_code
    FROM  
        tbl_product 
    WHERE 
        tbl_product.brand_name IN (SELECT * FROM dbo.splitstring(@brand_names)) 
        AND tbl_product.filter_code IN (SELECT * FROM dbo.splitstring(@type)) 
END

@brand_names这里是一串品牌名称,例如用逗号隔开

Apple,Samsung,Nokia

@type是产品的过滤器

 'Watch,Mobile,Tablet'

dbo.splitstring 函数将每个值从连接的字符串中分离出来,并将列表作为表格返回。因此,当用户同时选择品牌名称和类型时,查询会返回值,但如果用户仅选择品牌名称或类型,则查询不会返回任何内容。如果用户同时选择品牌名称和类型或不选择其中任何一个(您知道每个电子商务网站中的过滤器),我想进行查询以返回产品。如果用户没有选择任何过滤器,我将在变量中传递一个空字符串,例如如果用户没有选择任何品牌,那么@brand_names 将是@brand_names = ''

例如,如果用户选择品牌名称 Apple,则查询必须返回与该品牌相关的所有产品。同样,如果用户选择类型手表,则查询必须返回 Apple 品牌的手表。我正在使用 SQL Server 2008。

感谢您的帮助。

【问题讨论】:

  • dbo.splitstring => 这是您的自定义函数吗?也许使用 STRING_SPLIT(string, separator)。此外,CSV 作为参数也不是最好的主意。什么叫这个SP? C# 代码?

标签: sql sql-server-2008 stored-procedures


【解决方案1】:

对于这种“可选参数”查询,最后一个option recompile可以大大提高性能。

如果“未选择”参数是一个空字符串,那么你可以这样做:

WHERE 
   (@brand_names = '' or tbl_product.brand_name IN (SELECT * from dbo.splitstring(@brand_names)))
   and (@type = '' or tbl_product.filter_code IN (SELECT * from dbo.splitstring(@type)))
option (recompile)

option (recompile) 告诉 SQL 在每次过程运行时为此语句构建一个新计划。因此,例如,如果您为@brand_names 传递一个空字符串,引擎甚至不需要评估该谓词的or tbl_product.brand_name in ... 部分。如果您不这样做,那么 SQL 将一如既往地为第一次执行构建一个计划,然后在后续执行中重用该计划。当不同的参数值会对结果产生如此大的影响时,这并不是很好。

【讨论】:

  • 老兄,你真棒。非常感谢!。请问option recompile做了什么?
  • @ygssoni 我已经为答案添加了更多解释。
  • 重新编译强制服务器再次解释代码,丢弃任何现有计划......新的优化器运行将生成完全不同的执行计划,从而提高性能(在这种情况下)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-08
  • 2018-08-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多