【问题标题】:SQL Server select (top) two rows into two temp variablesSQL Server 选择(顶部)两行进入两个临时变量
【发布时间】:2016-02-26 18:46:14
【问题描述】:

我有一个查询导致两行或多行(只有一列),我想将第一行值捕获到第一个临时变量中,并将第二行值捕获到第二个临时变量中,而不使用多次选择顶部 1 和选择按 desc 排名前 1 位

类似的东西;

Select row1 value into @tempvariable1, row2 value into @tempvariable2 from blah blah

【问题讨论】:

标签: sql-server tsql select


【解决方案1】:

您需要以某种方式识别行(我在下面的示例中使用行 ID,按值排序 - 您可以按 id 或其他方式排序):

DECLARE @DataSource TABLE
(
    [value] VARCHAR(12)
);

INSERT INTO @DataSource
VALUES ('value 1')
      ,('value 2')
      ,('value 3');

DECLARE @tempVariable1 VARCHAR(12)
       ,@tempVariable2 VARCHAR(12);

WITH DataSource ([value], [rowID]) AS
(
    SELECT [value]
          ,ROW_NUMBER() OVER (ORDER BY [value])
    FROM @DataSource
)
SELECT @tempVariable1 = IIF([rowID] = 1, [value], @tempVariable1)
      ,@tempVariable2 = IIF([rowID] = 2, [value], @tempVariable2)
FROM DataSource;

SELECT @tempVariable1
      ,@tempVariable2;

【讨论】:

  • 欢呼@gotqn,最后但一个带有 iif 条件的选择帮助我调整了我的查询,它做到了。
【解决方案2】:

您可以使用 CTE 获取所需的 X 值,然后从中进行选择:

declare @data table(id int);
insert into @data(id) values(8), (6), (4), (3);

with vals(id, n) as (
    Select top(2) id, ROW_NUMBER() over(order by id)
    From @data      
) 
Select @A = (Select id From vals Where n = 1)
    , @B = (Select id From vals Where n = 2)

您也可以使用 PIVOT:

Select @A = [1], @B = [2]
From (
    Select id, ROW_NUMBER() over(order by id)
    From @data
) v(id, n)
PIVOT (
    max(id) FOR n in ([1], [2])
) as piv

【讨论】:

    【解决方案3】:

    你有两个选择

    假设我们的测试用例构建如下

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多