Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/27.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 更改内容的循环_Sql Server - Fatal编程技术网

Sql server 更改内容的循环

Sql server 更改内容的循环,sql-server,Sql Server,我真的很挣扎,应该是直截了当的,我有一个表格,格式如下: ID Date Agent State 1 02/01/2015 77777 Work 2 03/01/2015 77777 X 3 04/01/2015 77777 X 4 05/01/2015 77777 X 5 06/01/2015 77777 X 6 07/01/2015 77777 SICK 7 08/01/2015 77777 SICK 8

我真的很挣扎,应该是直截了当的,我有一个表格,格式如下:

ID  Date    Agent   State
1   02/01/2015  77777   Work
2   03/01/2015  77777   X
3   04/01/2015  77777   X
4   05/01/2015  77777   X
5   06/01/2015  77777   X
6   07/01/2015  77777   SICK
7   08/01/2015  77777   SICK
8   09/01/2015  77777   X
9   02/01/2015  88888   Work
10  03/01/2015  88888   Work
11  04/01/2015  88888   SICK
12  05/01/2015  88888   SICK
13  06/01/2015  88888   X
14  07/01/2015  88888   X
15  08/01/2015  88888   SICK
16  09/01/2015  88888   Work
我需要创建一个循环,用前一条记录的状态替换X,直到它到达一个不包含X的字段。它还必须适应代理ID的变化,并且如果代理的第一条记录是X,那么它应该显示“工作”

预期输出如下所示:

Date    Agent   State
02/01/2015  77777   Work
03/01/2015  77777   Work
04/01/2015  77777   Work
05/01/2015  77777   Work
06/01/2015  77777   Work
07/01/2015  77777   SICK
08/01/2015  77777   SICK
09/01/2015  77777   SICK
02/01/2015  88888   Work
03/01/2015  88888   Work
04/01/2015  88888   SICK
05/01/2015  88888   SICK
06/01/2015  88888   SICK
07/01/2015  88888   SICK
08/01/2015  88888   SICK
09/01/2015  88888   Work

我使用的是sql server management studio 2008

如果ID为1的行是
'X'
,则可以在update语句中使用子查询,并使用
合并
来分配
'Work'

update #statetable 
set [State] = COALESCE((select top 1 s2.[State] from #statetable as s2 where s2.ID < s1.ID AND s2.State <> 'X' order by s2.ID ),'Work')
from #statetable as s1
Where s1.[State] = 'X'

最直接的方法是使用光标

DECLARE @id int
DECLARE @agent int
DECLARE @state varchar(10)
DECLARE @previousAgent int = 0
DECLARE @previousState varchar(10) = 'Work'

DECLARE myCursor CURSOR FOR
    SELECT ID, Agent, State
    FROM MyTable
    ORDER BY Agent, Date

OPEN myCursor   
FETCH NEXT FROM myCursor INTO @id, @agent, @state

WHILE @@FETCH_STATUS = 0   
BEGIN
    IF @agent <> @previousAgent
    BEGIN
        SET @previousAgent = @agent
        SET @previousState = 'Work'
    END

    IF @state = 'X'
        UPDATE MyTable SET State = @previousState WHERE ID = @id
    ELSE
        SET @previousState = @state

    FETCH NEXT FROM myCursor INTO @id, @agent, @state
END

CLOSE myCursor
DEALLOCATE myCursor
DECLARE@id int
声明@agent int
声明@state varchar(10)
声明@previousAgent int=0
声明@previousState varchar(10)=“工作”
将myCursor声明为
选择ID、代理、状态
从MyTable
代理人的订单,日期
打开我的光标
从myCursor获取下一个到@id、@agent、@state
而@@FETCH\u STATUS=0
开始
如果@agent@previousAgent
开始
设置@previousAgent=@agent
SET@previousState='Work'
结束
如果@state='X'
更新MyTable集合状态=@previousState,其中ID=@ID
其他的
设置@previousState=@state
从myCursor获取下一个到@id、@agent、@state
结束
关闭我的光标
取消分配我的游标

Fiddle:

请详细说明这一部分“它还必须适应代理ID的变化,并且如果代理的第一个记录是X,那么它应该显示“工作”嗨,我的数据有3种状态(“X”=休息日或假日、生病或工作)如果代理的第一个状态为=“X”,那么我需要将其更改为“工作”因此循环将填充下面的记录,直到达到另一个“工作”或“生病”状态。代理id中的更改应重置循环,使其不会携带来自前一代理的状态。我希望这是有意义的。它看起来只使用ID和状态就可以了,但是当我尝试引入日期和代理ID字段时,它就不起作用了。它似乎改变了X的工作,即使前面的记录有一个生病的状态。我已经包括了日期和代理字段在我的样本中,它的工作和结果符合您的预期结果。可能是SQL脚本中的其他部分导致了错误。非常感谢Ruud,感谢您的帮助。
DECLARE @id int
DECLARE @agent int
DECLARE @state varchar(10)
DECLARE @previousAgent int = 0
DECLARE @previousState varchar(10) = 'Work'

DECLARE myCursor CURSOR FOR
    SELECT ID, Agent, State
    FROM MyTable
    ORDER BY Agent, Date

OPEN myCursor   
FETCH NEXT FROM myCursor INTO @id, @agent, @state

WHILE @@FETCH_STATUS = 0   
BEGIN
    IF @agent <> @previousAgent
    BEGIN
        SET @previousAgent = @agent
        SET @previousState = 'Work'
    END

    IF @state = 'X'
        UPDATE MyTable SET State = @previousState WHERE ID = @id
    ELSE
        SET @previousState = @state

    FETCH NEXT FROM myCursor INTO @id, @agent, @state
END

CLOSE myCursor
DEALLOCATE myCursor