3

我有一个日历表,我正试图用它来处理一些周末和假期问题。

结构很简单:

CREATE TABLE calendar
(
    daterank INT,
    thedate DATE
);

这个想法是每条记录都有一个日期等级​​,用于比较目的。非节假日的工作日具有递增的 daterank,周末和节假日的 daterank 等于前一个非节假日的工作日。

事实证明,为非节假日工作日设置 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
;

有任何想法吗?

4

4 回答 4

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
于 2013-05-28T21:25:24.927 回答
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;

请参阅带有演示的 SQL Fiddle

于 2013-05-28T21:27:39.187 回答
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。有些人厌恶这个古怪的更新,但在这种情况下,确保它正常工作是微不足道的。

于 2013-05-28T21:20:05.007 回答
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

演示

于 2013-05-28T21:36:16.267 回答