我有一张日历表,我正试图用它来处理一些周末和假期问题。
结构很简单:
CREATE TABLE calendar
(
daterank INT,
thedate DATE
);
这个想法是每条记录都有一个日期,用于比较目的。非假日工作日有增量日期,周末和假日的日期等于前一个非假日工作日。
为非假日工作日设置daterank比我想象的要容易,但设置周末和假期比我想象的要复杂。
数据的一个子集:
daterank thedate
881 2013-05-21
882 2013-05-22
883 2013-05-23
884 2013-05-24
NULL 2013-05-25
NULL 2013-05-26
885 2013-05-27
886 2013-05-28
887 2013-05-29
888 2013-05-30
889 2013-05-31
NULL 2013-06-01
在上面的例子中,我想要的是用884(5/24的值)替换5/25和5/26的NULL,用889替换6/1的NULL等等。
什么行不通:
UPDATE calendar c1
SET c1.daterank = (
SELECT MAX(c2.daterank)
FROM calendar c2
WHERE c2.thedate < c1.thedate
AND c2.daterank IS NOT NULL
)
WHERE daterank IS NULL
;
有什么想法吗?
答案 0 :(得分:2)
您不得对要更新的表使用别名。
UPDATE calendar
SET daterank = (
SELECT MAX(c2.daterank)
FROM calendar c2
WHERE c2.thedate < calendar.thedate
AND c2.daterank IS NOT NULL
)
WHERE daterank IS NULL
答案 1 :(得分:1)
您可以使用以下内容获得结果:
;with cte as
(
select daterank, thedate
from calendar
where daterank is null
)
update c
set c.daterank = d.daterank
from cte c
cross apply
(
select top 1 daterank, thedate
from calendar d
where d.thedate < c.thedate
and d.daterank is not null
order by daterank desc
) d;
答案 2 :(得分:0)
你可以使用古怪的更新,我相信这应该有效:
CREATE CLUSTERED INDEX idx_Cal ON calendar (daterank)
GO
DECLARE @Prev_Dt_Rank BIGINT
UPDATE calendar
SET daterank = CASE WHEN daterank IS NULL THEN @Prev_Dt_Rank
ELSE daterank
END
,@Prev_Dt_Rank = daterank
FROM calendar
WITH (TABLOCKX)
OPTION (MAXDOP 1)
GO
索引是必不可少的,第一个daterank不能为NULL。 有些人对这种奇怪的更新感到厌恶,但在这样的情况下,确保它正常工作是微不足道的。
答案 3 :(得分:0)
这是我的尝试;)
;WITH cte AS
(
SELECT t.r, t.d
FROM t
WHERE t.r IS NOT NULL
)
, tbl AS
(
SELECT
(
SELECT cte.r
FROM cte
WHERE cte.d = (SELECT MAX(sub.d)
FROM cte sub
WHERE sub.d <= t.d)
) AS r,
t.d
FROM t
)
UPDATE t
SET t.r = tbl.r
FROM t
JOIN tbl ON tbl.d = t.d
WHERE t.r IS NULL
SELECT * FROM t