declare @t int
set @t = 10
if (o = 'mmm') set @t = -1
select top(@t) * from table
如果我想要的话通常会产生10行,但很少全部。
我知道我可以通过“SET ROWCOUNT”来做到这一点。但是有一些变量数,比如-1,导致TOP产生所有元素。
答案 0 :(得分:31)
可传递给TOP
的最大可能值为9223372036854775807
,因此您可以传递该值。
下面我使用max signed bigint的二进制形式,因为只要你知道基本模式并且bigint是8个字节就更容易记住。
declare @t bigint = case when some_condition then 10 else 0x7fffffffffffffff end;
select top(@t) *
From table
如果你没有order by子句,那么前10名将只是10和依赖于优化。
如果你确实有一个order by子句来定义前10个和一个支持它的索引,那么上面查询的计划应该适用于任何可能的值。
如果您没有支持索引且计划显示排序,则应考虑拆分为两个查询。
答案 1 :(得分:5)
我不确定我理解你的问题。
但如果你有时想要TOP而其他时候不要只使用if / else construct:
if (condition)
'send TOP
SELECT TOP 10 Blah FROM...
else
SELECT blah1, blah2 FROM...
答案 2 :(得分:2)
您可以使用动态SQL(但我个人尝试避免动态SQL),您可以在其中创建要从条件或参数运行的语句的字符串。 这里还有一些关于如何在没有动态SQL的情况下做到这一点的好信息:
答案 3 :(得分:1)
动态的sql版本并不难做到。
CREATE PROCEDURE [dbo].[VariableTopSelect]
-- Add the parameters for the stored procedure here
@t int
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
declare @sql nvarchar(max)
if (@t=10)
begin
set @sql='select top (10) * from table'
end
else
begin
set @sql='select * from table'
end
exec sp_executesql @sql
END
使用此sp,如果他们向sp发送10,它将选择前10名,否则它将全部选择。
答案 4 :(得分:1)
也可以使用UNION和参数
SELECT DISTINCT TOP 10
Column1, Column2
FROM Table
WHERE @ShowAllResults = 0
UNION
SELECT DISTINCT
Column1, Column2
FROM Table
WHERE @ShowAllResults = 1
答案 5 :(得分:1)
我找到的最佳解决方案是将所有条件中所需的列选择到临时表中,然后执行条件顶部:
DECLARE @TempTable TABLE(cols...)
INSERT INTO @TempTable
SELECT blah FROM ...
if (condition)
SELECT TOP 10 * FROM @tempTable
else
SELECT * FROM @tempTable
通过这种方式,您可以关注DRY,获得有条件的TOP,并且同样易于阅读。
干杯。
答案 6 :(得分:1)
declare @top bigint = NULL
declare @top_max_value bigint = 9223372036854775807
if (@top IS NULL)
begin
set @top = @top_max_value
end
select top(@top) *
from [YourTableName]
答案 7 :(得分:0)
使用语句" SET ROWCOUNT @ recordCount"在结果查询的开头。变量" @ recordCount"可以是任何正整数。返回所有记录应为0。
这意味着," SET ROWCOUNT 0"将返回所有记录和" SET ROWCOUNT 15"将仅返回结果集的前15行。
在处理大量记录时,缺点可能是性能损失。此外,SET ROWCOUNT将在整个查询的执行范围内有效。