你有两个选择
假设我们的测试用例构建如下
create table dbo.Test
(
value varchar(100) not null
)
GO
insert into dbo.Test
values
('A'),('B'),('NO THIS ONE'),('NO THIS ONE'),('NO THIS ONE')
GO
现在假设您按如下方式获取数据
select t.value
from dbo.Test t
where t.value != 'NO THIS ONE'
GO
第一个也是更简单的选择是将数据保存在临时表中
declare @results as Table (value varchar(100))
insert into @results
select t.value
from dbo.Test t
where t.value != 'NO THIS ONE'
您仍然使用 TOP 1,但不是在整个数据中,而是在结果中。
使用TOP 1 查找第一个结果和第二个TOP 1,其中值与第一个不同。
declare @A varchar(100), @B varchar(100)
set @A = (select top 1 r.value from @results r)
set @B = (select top 1 r.value from @results r where r.value != @A)
select @A, @B
GO
这种方法具有性能优势。
当然,如果两个值相等,那效果就不太好了。您可以通过使用top 1 并以相反的顺序排序来修复它。
有一个更好的选择使用rownumber。
它之所以有效,是因为如果您在返回多行时设置一个变量,该变量会与最后一个保持一致(实际上它会在每次行迭代时重置)。
case 语句确保变量@A 仅在第一行迭代时设置。
declare @A varchar(100), @B varchar(100)
/* This way @B receives the last value and @A the first */
select @B = t.value,
@A = (case when ROW_NUMBER() OVER(order by t.Value) = 1
then t.Value else @A
end)
from dbo.Test t
where t.value != 'NO THIS ONE'
select @A, @B