我在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
这将生成像这样的输出
但我只是希望如果BookUsed中的1st 1检测到变量增加并保持到最后1。
如果检测到0,则它再次向对应该记录的KeepTIme输入0
我想要的Exact输出是
所有这些都将在单一更新查询中。
提前致谢。
答案 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