Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 基于模式sqlserver的更新序列_Sql Server_Sql Server 2008_While Loop - Fatal编程技术网

Sql server 基于模式sqlserver的更新序列

Sql server 基于模式sqlserver的更新序列,sql-server,sql-server-2008,while-loop,Sql Server,Sql Server 2008,While Loop,对于这个问题,我无法引用正确的答案 下面是我的桌子 预期输出:具有ID和SequenceNo列。无法上载图像 ID Act SequenceNo1 1 1 1 2 2 NULL 3 3 NULL 4 4 NULL 5 1 5 6 2 NULL 7 3 NULL 8 4 NULL 9 5 NULL 10 6 NULL 11 5 11 12 6 NULL 13 1 13 14 2 NULL 15

对于这个问题,我无法引用正确的答案

下面是我的桌子

预期输出:具有ID和SequenceNo列。无法上载图像

ID  Act SequenceNo1
1   1   1
2   2   NULL
3   3   NULL
4   4   NULL
5   1   5
6   2   NULL
7   3   NULL
8   4   NULL
9   5   NULL
10  6   NULL
11  5   11
12  6   NULL
13  1   13
14  2   NULL
15  3   NULL
16  4   NULL
17  5   NULL
18  6   NULL
19  1   19
20  2   NULL
21  3   NULL
22  4   NULL
23  5   NULL
24  6   NULL
在开始处,最后一列SequenceNo为空`

我的要求是,每当启动新的Act列系列时,将ID列的值更新为SequenceNo列

Act列的值为1到6。在某些情况下,Act中可能缺少1到6之间的任何数字

示例1:ID1到4-Act正确,但在下一行中,ID=5 Act重新启动。因此需要更新SequenceNo列

例2:ID5到10是正确的。但下一行ID=11;Act=5具有新序列,因此需要更新SequenceNo列

我已经建立了一个逻辑,但这很耗时

DECLARE  @Act INT, @iStart INT, @iMax INT, @iFirst INT
    SET @iFirst = 7
    SET @iMax = (SELECT MAX(ID) FROM #tmp)
    SET @iStart = 1
    WHILE(@iStart <= @iMax)
    BEGIN   
        SET @Act = (SELECT Act FROM #tmp WHERE ID = @iStart) 
        IF(@iFirst > @Act )
        BEGIN
            UPDATE #tmp SET SequenceNo = @iStart WHERE ID = @iStart     
        END
        SET @iFirst = @Act
        SET @iStart = @iStart + 1
    END

我正在寻找任何可选的优化解决方案。

这是您想要的吗

update tupd
set
    SequenceNo = tupd.ID
from (
    select
    *
        , LAG(t.Act, 1, null) over(order by t.ID) as LagAct
    from #tmp t
) tt
inner join #tmp tupd on tt.ID = tupd.ID
where tt.Act < tt.LagAct


select
*
from #tmp tt
order by tt.ID
;使用CTE 像 按[DayOfWeek]顺序按Act RN在分区上选择ID、Act、RANK 来自tmp 更新t 设置t.SequenceNo=t.id 来自tmp t 内连接CTE C 在t.ID=C.ID上 其中C.RN=1
如果将当前行与上一行进行比较,可以在Act序列中找到中断。在当前的SQL Server版本中,ie 2012+可以使用LAG方法实现这一点。在以前的版本中,必须对当前ID值及其以前的值执行自联接。如果当前和先前Act值之间的差值不是1,则序列中存在中断。这仅在ID中没有间隙时有效

对于Act重新启动的每一行,此查询将在SeqBreak列中返回1

您可以在CTE中使用此选项仅选择Act中断的行。至少在SQL Server 2014中,您可以直接更新CTE

with x as (
    select 
        t1.ID,
        t1.SequenceNo ,
        case when t1.act = t2.act+1 then '0' else '1' end as SeqBreak
    from #tmp t1 left join #tmp t2 on t1.id=t2.id+1 )
update x
set SequenceNo=x.ID
where seqbreak=1 and id>1
如果在SQL Server 2008中不起作用,则必须在cte和表之间联接:

with x as (
    select 
        t1.ID,
        t1.SequenceNo ,
        case when t1.act = t2.act+1 then '0' else '1' end as SeqBreak
    from #tmp t1 left join #tmp t2 on t1.id=t2.id+1 )
update #tmp
set SequenceNo=x.ID
from #tmp inner join x on x.ID=#tmp.ID
where seqbreak=1 and #tmp.id>1
使用LAG(SQL Server 2012中的窗口功能之一)的等效查询更简单,速度是原来的两倍,因为它避免了自联接:

with x as (
    select 
        ID,
        SequenceNo ,
        case when act = 1 +LAG(act,1) OVER (ORDER BY ID)  then '0' else '1' end as SeqBreak
    from #tmp)
update x
set SequenceNo=x.ID
where seqbreak=1 and id>1

如果我在下面正确地回答了您的问题,查询应该会得到所需的结果

             update t3 set sequenceno = t3.id 
from
            #temp t1
            cross apply (select id+1 as idsum 
        from #temp 
            tmp where t1.id = tmp.id)t2
            inner join #temp t3
            on t3.id = t2.idsum
where t1.act>t3.act

MySQL是另一种rdbms产品,它与ms sql server无关。请在您的问题中只使用相关的产品标签。您使用的是什么版本的sql server?另外,您是否可以编辑您的问题以添加DDL+DML示例数据?SQL Server 2012具有排名和窗口功能,如行数、排名、领先、滞后等,使此查询变得简单。它也是受支持的最早的SQL Server版本。在以前的版本中,有一些方法可以在没有循环的情况下检测序列中的中断,尽管它们更难编写。也许您应该转移到受支持的服务器版本?例如,在序列中查找断点只需要找到Act-LAGAct,1与1@PanagiotisKanavos-谢谢。但是我有MicrosoftSQLServer2008SP3-10.0.5520.0x64版本。还有其他帮助吗?我的版本是Microsoft SQL Server 2008 SP3-10.0.5520.0 X64。由于未启用并行数据仓库PDW功能,我收到了一个错误。@AK47正如我在评论中提到的,这些不是PDW功能,而是SQL Server 2012+功能。您正在运行一个非常旧的10年不受支持的版本。这使得写答案更加困难。您可以尝试对匹配的列进行自联接,以尝试在sequenceI want ID值字段中查找SequenceNo字段中的前几行。你的查询对我没有帮助。你能举例说明序列应该是什么样子吗?也更新了我的答案。现在检查它是否符合您的要求。添加了预期输出。
with x as (
    select 
        ID,
        SequenceNo ,
        case when act = 1 +LAG(act,1) OVER (ORDER BY ID)  then '0' else '1' end as SeqBreak
    from #tmp)
update x
set SequenceNo=x.ID
where seqbreak=1 and id>1
             update t3 set sequenceno = t3.id 
from
            #temp t1
            cross apply (select id+1 as idsum 
        from #temp 
            tmp where t1.id = tmp.id)t2
            inner join #temp t3
            on t3.id = t2.idsum
where t1.act>t3.act