更新与SQL Server中其他列对应的列

时间:2018-04-24 04:02:41

标签: sql sql-server database

我在SQL Server中遇到问题,我的查询是

CREATE TABLE BookRecord
(
     BookId INT IDENTITY(1, 1),
     BookUsed INT
)

INSERT INTO BookRecord 
VALUES (1), (1), (0), (0), (1), (1), (0), (1)

ALTER TABLE BookRecord 
    ADD KeepTime INT

DECLARE @time INT = 0

UPDATE book1 
SET @time = KeepTime = CASE
                          WHEN book1.BookUsed = 1 
                             THEN 
                                CASE 
                                   WHEN book2.BookUsed IS NULL OR 
                                        book2.BookUsed = 0 
                                      THEN @time + 1 
                                      ELSE @time 
                                END 
                             ELSE 0 
                       END
FROM
    BookRecord book1 
LEFT JOIN 
    BookRecord book2 ON book1.BookId - 1 = book2.BookId

SELECT * 
FROM BookRecord

这将生成像这样的输出

enter image description here

但我只是希望如果BookUsed中的1st 1检测到变量增加并保持到最后1。

如果检测到0,则它再次向对应该记录的KeepTIme输入0

我想要的Exact输出是

enter image description here

所有这些都将在单一更新查询中。

提前致谢。

4 个答案:

答案 0 :(得分:1)

如果是,请尝试使用触发器:

CREATE TRIGGER BookUsedTrigger
 ON BookRecord 
FOR UPDATE
AS
    Update BookRecord set BookRecord.KeepTime = BookRecord.KeepTime +1 from inserted i inner join deleted d on i.BookId = d. BookId where i.BookUsed = 1 and d.BookUsed = 0 and BookRecord.BookId = i.BookId
GO

执行此触发后,您只需更新BookUsed标志

即可
UPDATE BookRecord SET BookUsed = 1 WHERE --some condition

如果它将BookUsed从0变为1,它将触发并增加KeepTime

如果您无法使用任何触发器,我担心您需要像这样检查更新

UPDATE BookRecord
SET BookUsed = 1,
    KeepTime =  CASE  
    WHEN BookUsed = 0 THEN KeepTime + 1
    ELSE KeepTime
    END 
WHERE -- your conditions

但请注意,不要将CASE放在其他更新脚本中,而不是更新BookUsed为1或者您只想对任何案例进行单一更新使用此

UPDATE BookRecord
SET BookUsed = @flag,
    KeepTime =  CASE  
    WHEN BookUsed = 0 and @flag = 1 THEN KeepTime + 1
    ELSE KeepTime
    END 
WHERE -- your conditions

@flag是你的参数或只是用值替换它但我建议发送参数来查询而不是直接连接它

答案 1 :(得分:1)

对SQL Server 2008使用recursive CTE。我在第一次CTE中使用row_number只是为了确保没有间隙

with cte as (
    select
        Bookid, BookUsed, rn = row_number() over (order by BookId)
    from 
        BookRecord
)
, rcte as (
    select
        rn, Bookid, BookUsed
        , KeepTime = BookUsed, cnt = BookUsed
    from
        cte
    where rn = 1

    union all

    select
        c.rn, c.BookId, c.BookUsed
        , case
            when c.BookUsed = 0 then 0
            else        
                r.cnt + case when r.BookUsed = 0 and c.BookUsed = 1 then 1 else 0 end
        end
        , r.cnt + case when r.BookUsed = 0 and c.BookUsed = 1 then 1 else 0 end
    from
        rcte r
        join cte c on r.rn + 1 = c.rn
)

update b
set b.KeepTime = r.KeepTime
from
    BookRecord b
    join rcte r on b.BookId = r.BookId

select * from BookRecord

输出

BookId   BookUsed   KeepTime
-----------------------------
1        1          1
2        1          1
3        0          0
4        0          0
5        1          2
6        1          2
7        0          0
8        1          3

答案 2 :(得分:1)

您可以在此处使用row_number()功能:

select Bookid, Bookused, (case when Bookused = 0 then 0
                               when (Bookid - Seq) > 0 then (Bookid - Seq)
                          else 1 end) as KeepTime
from (select *,
              row_number() over (partition by BookUsed order by Bookid) Seq
      from BookRecord  b
     ) t
order by Bookid;

您可以利用身份列(Bookid)生成新的部门(BookUsed)序列,并将它们的差异用作(Bookid - Seq)为KeepTime

答案 3 :(得分:1)

你只是错过了几行。当您通过大小写时间也返回“0”并且变量从“0”开始更新变量时。这就是为什么你的列值总是返回并显示“1”。

使用此更新查询而不是您的

UPDATE book1 SET @time = CASE
                          WHEN book1.BookUsed = 1 AND (book2.BookUsed IS NULL OR book2.BookUsed = 0)
                             THEN 
                               @time + 1 
                             ELSE @time 
                          END,
                 KeepTime = CASE
                             WHEN book1.BookUsed = 1 
                               THEN 
                                 @time 
                               ELSE 0 
                             END
FROM
    BookRecord book1 
LEFT JOIN 
    BookRecord book2 ON book1.BookId - 1 = book2.BookId