更改内容的循环

时间:2015-09-16 09:54:01

标签: 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   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

2 个答案:

答案 0 :(得分:1)

您可以在更新语句中使用子查询,如果ID为1的行为COALESCE,则'Work'可以指定'X'

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'

这是sqlfiddle of the code I used to test it.

注意:

如果您将表State列声明为类型varchar且没有长度,则会抛出错误。

  

字符串或二进制数据将被截断。

Because a varchar without a length will default to 1.所以这样定义的表格不起作用。

CREATE TABLE #statetable ( [ID] int, [State] varchar );

答案 1 :(得分:1)

最直接的方法是使用光标。

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

小提琴:http://sqlfiddle.com/#!3/20716/1/0