【问题标题】:Take next N rows recursively and sequentially from sql table从 sql 表中递归顺序地获取下 N 行
【发布时间】:2013-11-25 04:54:01
【问题描述】:

我有两个表“主要”和“移动”。 “主”表有记录,我通过执行存储过程将 3 行顺序移动到“移动”表。因此,每次我执行存储过程时,它应该检查下一组 3 行是否从最后一次移动发生的行中的“主”表中顺序读取并插入到“移动”表中。

select rowid from @main
rowid
-----------------------
1
2
3
4
5

现在当我执行查询时,它应该从“主”表中取出 3 行并插入到“移动”表中。假设我运行查询 5 次,这就是我希望每次运行时“已移动”表包含的方式。

1,2,3 --"moved" table has these rows 1st time when I run the query
4,5,1 --"moved" table has these rows 2nd time when I run the query
2,3,4 --"moved" table has these rows 3rd time when I run the query
5,1,2 --"moved" table has these rows 4th time when I run the query
3,4,5 --"moved" table has these rows 5th time when I run the query
1,2,3 --"moved" table has these rows 6th time when I run the query

...所以顺序读取继续。从上次运行结束的下一行开始按顺序读取。

我已经问过了,但答案只是部分有效。当“主”表中的值按顺序增长或不按顺序增长时,它不起作用。

提前感谢您的帮助。

【问题讨论】:

  • 没有ORDER BY 子句就没有顺序,sequential 没有意义。您想使用哪一列来指定从@main 中获取的值的顺序? (似乎只有一列,您不喜欢它提供的结果。)
  • “Main”表是基表,只有一列“RowID”。而“已移动”表是也只有一列“RowID”的目标表。我正在尝试从上到下读取行,并在到达表末尾时再次从顶部开始 - 递归。只要我得到上面给定的输出,查询就可以是任何东西。主表只有“RowID”列。

标签: sql-server-2008-r2 sql-server-2012 common-table-expression


【解决方案1】:

以下示例可以为您提供一个起点。请注意,必须为您要插入的值提供明确的顺序。表格没有自然顺序,“顺序”毫无意义。

-- Sample data.
declare @Template as Table ( TemplateValue VarChar(10), TemplateRank Int );
-- NB: TemplateRank values are assumed to start at zero and be dense.
insert into @Template ( TemplateValue, TemplateRank ) values
  ( 'one', 0 ), ( 'two', 1 ), ( 'three', 2 ), ( 'four', 3 );
declare @NumberOfTemplateValues Int = ( select Max( TemplateRank ) from @Template ) + 1;
select * from @Template;

declare @AccumulatedStuff as Table ( Id Int Identity, Value VarChar(10) );
declare @GroupSize as Int = 5;

-- Add a block of   GroupSize   rows to the   AccumulatedStuff .
declare @LastValue as VarChar(10) = ( select top 1 Value from @AccumulatedStuff order by Id desc );
declare @LastRank as Int = ( select TemplateRank from @Template where TemplateValue = @LastValue );
select @LastValue as LastValue, @LastRank as LastRank;

with Numbers as (
  select 1 as Number
  union all
  select Number + 1
    from Numbers
    where Number < @GroupSize ),
  RankedValues as (
    select TemplateValue, TemplateRank
      from @Template as T inner join
        Numbers as N on ( N.Number + Coalesce( @LastRank, @NumberOfTemplateValues - 1 ) ) % @NumberOfTemplateValues = T.TemplateRank )
  insert into @AccumulatedStuff
    select TemplateValue from RankedValues;

select * from @AccumulatedStuff;

-- Repeat.
set @LastValue = ( select top 1 Value from @AccumulatedStuff order by Id desc );
set @LastRank = ( select TemplateRank from @Template where TemplateValue = @LastValue );
select @LastValue as LastValue, @LastRank as LastRank;

with Numbers as (
  select 1 as Number
  union all
  select Number + 1
    from Numbers
    where Number < @GroupSize ),
  RankedValues as (
    select TemplateValue, TemplateRank
      from @Template as T inner join
        Numbers as N on ( N.Number + Coalesce( @LastRank, @NumberOfTemplateValues - 1 ) ) % @NumberOfTemplateValues = T.TemplateRank )
  insert into @AccumulatedStuff
    select TemplateValue from RankedValues;

select * from @AccumulatedStuff;

【讨论】:

  • 感谢您的时间和代码 HABO!真的很感激。只是希望它简单,而不是在显式循环中重复。抱歉,我无法在我的帖子中清楚地解释我的问题,否则我相信你现在已经回答了。自己想通了,如果您想了解我在上面所说的内容,请在下面发布查询。对不起,我的解释很糟糕。在花了这么多小时之后,我有点分层。不过还是非常感谢!!!
【解决方案2】:
DECLARE @main TABLE
(
    RowID INT IDENTITY(1,1),
    DataID INT
)
DECLARE @selected TABLE
(
    RowID INT IDENTITY(1,1),
    DataID INT
)

DECLARE @final TABLE
(
    RowID INT IDENTITY(1,1),
    DataID INT
)

INSERT INTO @main values (1),(2),(3),(4),(5),(6),(7)
--INSERT INTO @Selected values (1),(2),(3)
--INSERT INTO @Selected values (4),(5),(6)
--INSERT INTO @Selected values (7),(1),(2)
--INSERT INTO @Selected values (3),(4),(5)
INSERT INTO @Selected values (6),(7),(1)
--INSERT INTO @Selected values (2),(3),(4)
--INSERT INTO @Selected values (5),(6),(7)
--INSERT INTO @Selected values (1),(2),(3)

DECLARE 
    @LastDataID INT,
    @FinalCount INT

SELECT  
    TOP 1 
    @LastDataID = DataID 
FROM 
    @selected 
ORDER BY 
    RowID 
DESC 

INSERT INTO @final
    SELECT 
        TOP 3
        DataID
    FROM 
        @main
    WHERE
        DataID > @LastDataID 

SELECT @FinalCount = COUNT(1) FROM @final

IF (ISNULL(@FinalCount, 0 ) < 3)
BEGIN
    INSERT INTO @final
        SELECT 
            TOP (3 - @FinalCount)
            DataID
        FROM
            @main      
END

SELECT * FROM @final

关键是要引用移动到“已移动/已选择”表的最后一条记录。它按预期工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-04-23
    • 2021-04-20
    • 1970-01-01
    • 2020-11-03
    • 1970-01-01
    • 1970-01-01
    • 2020-09-20
    • 1970-01-01
    相关资源
    最近更新 更多