SQL查询中的可选参数

时间:2016-03-12 19:10:05

标签: sql sql-server sql-server-2012

我是SQL的新手,我有点迷茫。我有一个包含产品的表格,包括productnamecategory等各种字段。

我希望有一个查询,我可以这样说:选择某个类别中产品名称中包含特定字词的所有产品。复杂因素是我只想返回该子集的特定范围。所以我也想说回到那个符合该规范的100到120种产品。

我用Google搜索并找到了这个查询:

WITH OrderedRecords AS
(   
    SELECT *, ROW_NUMBER() OVER (ORDER BY PRODUCTNUMMER) AS "RowNumber",
    FROM (
        SELECT * 
        FROM SHOP.dbo.PRODUCT
        WHERE CATEGORY = 'ARDUINO'
        and PRODUCTNAME LIKE '%yellow%'
    )
) 
SELECT * FROM OrderedRecords WHERE RowNumber BETWEEN 100 and 120
Go

查询在某种程度上有效,但是在过滤之前它会分配行号,因此我将无法获得足够的记录,如果没有参数,我不知道如何处理它。理想情况下,我希望能够不提供类别和搜索词,它只列出所有产品。

我不知道如何实现这一点,任何帮助表示赞赏!

3 个答案:

答案 0 :(得分:3)

如果您只需要对查询进行分页并返回特定范围的结果,则可以使用OFFSET FETCH Clause

这样就不需要按RowNumber过滤结果项了。我认为这个解决方案更容易:

SELECT * 
FROM SHOP.dbo.PRODUCT
WHERE CATEGORY = 'ARDUINO' AND PRODUCTNAAM LIKE '%yellow%'
ORDER BY PRODUCTNUMMER
OFFSET 100 ROWS          -- start row
FETCH NEXT 20 ROWS ONLY  -- page size

了解更多Pagination with OFFSET / FETCH

答案 1 :(得分:3)

基于esiprogrammer在答案中显示的关于如何使用分页仅返回特定范围内的行的内容。

你的第二个问题是:

  

理想情况下,我希望能够不提供类别和搜索词,它只会列出所有产品。

您可以有两个查询/存储过程,一个用于使用特定参数进行查找,另一个用于不带参数的查找。

或者,如果您坚持为所有案例保留一个查询/存储过程,则有两个选项:

  1. 构建仅包含存在的过滤器的动态SQL语句;使用EXECUTE (@sql)EXECUTE sp_executesql @sql
  2. 执行此操作
  3. 构建Catch-All查询
  4. 选项2的示例:

    -- if no category is given, it will be NULL
    DECLARE @search_category VARCHAR(128);
    
    -- if no name is given, it will be NULL
    DECLARE @search_name VARCHAR(128);
    
    SELECT * 
    FROM SHOP.dbo.PRODUCT
    WHERE (@search_category IS NULL OR CATEGORY=@search_category) AND
          (@search_name IS NULL OR PRODUCTNAAM LIKE '%'+@search_name+'%')
    ORDER BY PRODUCTNUMMER
    OFFSET 100 ROWS
    FETCH NEXT 20 ROWS ONLY
    OPTION(RECOMPILE); -- generate a new plan on each execution that is optimized for that execution’s set of parameters
    

答案 2 :(得分:0)

你在过滤之前分配rownumber是什么意思? Category和ProductName是子查询的一部分...因此,如果产品表具有10k记录且只有1k符合您的标准,则CTE的结果将为1k,因此RowNumber BETWEEN 100和120可以工作。测试一下,从select语句中删除where子句,然后获得所有产品表的rownumber。然后在类别和产品名称过滤器中添加回来,并且您的RowNumber用于按ProductNumber排序的过滤器,因此当您在100和120之间添加时,这是基于您所描述的内容的正确解决方案。

WITH OrderedRecords AS
(   
        SELECT ROW_NUMBER() OVER (ORDER BY PRODUCTNUMMER) AS "RowNumber"
            , * 
        FROM SHOP.dbo.PRODUCT
        WHERE CATEGORY = 'ARDUINO'
        and PRODUCTNAAM LIKE '%yellow%'
    )
) 
SELECT * 
FROM OrderedRecords 
WHERE RowNumber 
BETWEEN 100 and 120
Go