我无法为问题引用正确的图块。
以下是我的表格。
预期输出:使用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
为NULL。
我的要求是,每当启动ID
列的新系列时,都会将SequenceNo
列的值更新为Act
列。
Act
列的值为1到6.可能会出现Act
中缺少1到6之间的任何数字。
示例1:ID
1到4 - Act
是正确的,但在下一行(ID
= 5)Act
重新启动。因此需要更新SequenceNo
列。
示例2:ID
5到10是正确的。但是下一行(ID
= 11; Act
= 5)有新序列,因此需要更新SequenceNo
列。
CREATE TABLE #tmp
(
ID int
, ScheduleID varchar(50)
,DCNumber VARCHAR(50)
, BuildingID varchar(10)
, StoreNumber int
, [DayOfWeek] int
, [Tm] varchar(10)
,[Act] int
, SequenceNo int
)
INSERT INTO #tmp SELECT 1,'WAS',9003,900301,254,1,'00:00',1,NULL
INSERT INTO #tmp SELECT 2,'WAS',9003,900301,254,1,'00:00',2,NULL
INSERT INTO #tmp SELECT 3,'WAS',9003,900301,254,1,'00:00',3,NULL
INSERT INTO #tmp SELECT 4,'WAS',9003,900301,254,1,'00:00',4,NULL
INSERT INTO #tmp SELECT 5,'WAS',9003,900301,254,2,'00:00',1,NULL
INSERT INTO #tmp SELECT 6,'WAS',9003,900301,254,2,'00:00',2,NULL
INSERT INTO #tmp SELECT 7,'WAS',9003,900301,254,2,'00:00',3,NULL
INSERT INTO #tmp SELECT 8,'WAS',9003,900301,254,2,'00:00',4,NULL
INSERT INTO #tmp SELECT 9,'WAS',9003,900301,254,2,'00:00',5,NULL
INSERT INTO #tmp SELECT 10,'WAS',9003,900301,254,2,'00:00',6,NULL
INSERT INTO #tmp SELECT 11,'WAS',9003,900301,254,3,'00:00',5,NULL
INSERT INTO #tmp SELECT 12,'WAS',9003,900301,254,3,'00:00',6,NULL
INSERT INTO #tmp SELECT 13,'WAS',9003,900301,254,4,'00:00',1,NULL
INSERT INTO #tmp SELECT 14,'WAS',9003,900301,254,4,'00:00',2,NULL
INSERT INTO #tmp SELECT 15,'WAS',9003,900301,254,4,'00:00',3,NULL
INSERT INTO #tmp SELECT 16,'WAS',9003,900301,254,4,'00:00',4,NULL
INSERT INTO #tmp SELECT 17,'WAS',9003,900301,254,5,'00:00',5,NULL
INSERT INTO #tmp SELECT 18,'WAS',9003,900301,254,5,'00:00',6,NULL
INSERT INTO #tmp SELECT 19,'WAS',9003,900301,254,6,'00:00',1,NULL
INSERT INTO #tmp SELECT 20,'WAS',9003,900301,254,6,'00:00',2,NULL
INSERT INTO #tmp SELECT 21,'WAS',9003,900301,254,6,'00:00',3,NULL
INSERT INTO #tmp SELECT 22,'WAS',9003,900301,254,6,'00:00',4,NULL
INSERT INTO #tmp SELECT 23,'WAS',9003,900301,254,7,'00:00',5,NULL
INSERT INTO #tmp SELECT 24,'WAS',9003,900301,254,7,'00:00',6,NULL
我已经构建了一个逻辑,但这很耗时。
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
我正在寻找任何其他优化解决方案。
答案 0 :(得分:0)
这是你想要的吗?
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
答案 1 :(得分:0)
;WITH CTE
AS
(
SELECT ID,Act,RANK() OVER (PARTITION BY [DayOfWeek] ORDER BY Act) RN
FROM #tmp
)
UPDATE t
SET t.SequenceNo = t.id
FROM #tmp t
inner join CTE C
ON t.ID = C.ID
WHERE C.RN = 1
答案 2 :(得分:0)
如果将当前行与之前的行进行比较,则可以在Act
序列中找到中断。在当前的SQL Server版本中,即2012+,您可以使用LAG()方法执行此操作。在以前的版本中,您必须对当前ID值及其先前值执行自联接。如果当前和先前Act
值之间的差值不是1,则序列中断。这仅适用于ID中没有间隙的情况。
此查询将在Act
重新启动的每一行的SeqBreak列中返回1
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
您可以在CTE中使用它来仅选择Act
中断的行。您可以直接更新CTE,至少在SQL Server 2014中。
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
答案 3 :(得分:0)
如果我在下面正确地提出您的问题,则查询应该获取所需的结果。
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