是否有一个可选的TOP子句任何现有的,优雅的,模式?

Ale*_*lan 5 sql sql-server

取(简化的)存储过程定义这里:

create procedure get_some_stuffs
  @max_records int = null
as
begin
  set NOCOUNT on

  select top (@max_records) *
  from my_table
  order by mothers_maiden_name
end
Run Code Online (Sandbox Code Playgroud)

我想限制所选记录的数量,如果只 @max_records提供。

问题:

  1. 真正的查询是肮脏和大; 我想避免重复此操作:

    if(@max_records is null)
    begin
      select *
      from {massive query}
    end
    else
    begin
      select top (@max_records)
      from {massive query}
    end
    
    Run Code Online (Sandbox Code Playgroud)
  2. 任意定点值感觉不对:

    select top (ISNULL(@max_records, 2147483647)) *
    from {massive query}
    
    Run Code Online (Sandbox Code Playgroud)

    例如,如果@max_recordsnull{massive query}返回小于2147483647行,这将是相同的:

    select * 
    from {massive query}
    
    Run Code Online (Sandbox Code Playgroud)

    或者是有某种惩罚的选择top (2147483647) *从表中只有50行?

是否有其他现有模式可用于可选地限制计数的结果集,而无需重复查询或使用标记值?

Cᴏʀ*_*ᴏʀʏ 2

我正在考虑这个问题,虽然我喜欢IFProblem 1声明中的明确表述,但我理解重复的问题。因此,您可以将主查询放在单个 CTE 中,并使用一些技巧从中查询(粗体部分是此解决方案的亮点):

CREATE PROC get_some_stuffs
(
    @max_records int = NULL
)
AS
BEGIN
    SET NOCOUNT ON;

    WITH staged AS (
        -- Only write the main query one time
        SELECT * FROM {massive query}
    )
    -- This part below the main query never changes:
    SELECT * 
    FROM (
        -- A little switcheroo based on the value of @max_records
        SELECT * FROM staged WHERE @max_records IS NULL
        UNION ALL
        SELECT TOP(ISNULL(@max_records, 0)) * FROM staged WHERE @max_records IS NOT NULL
    ) final
    -- Can't use ORDER BY in combination with a UNION, so move it out here
    ORDER BY mothers_maiden_name
END
Run Code Online (Sandbox Code Playgroud)

UNION ALL我查看了每个查询的实际查询计划,优化器足够聪明,可以完全避免不需要运行的部分。

之所以ISNULL(@max_records, 0)存在在那里,是因为TOP NULL无效,并且无法编译。