2013-05-28 33 views
3

我有一個日曆表,我試圖用來處理一些週末和假期問題。更新記錄與子查詢到自己的表

結構簡單:

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 

我想要什麼,在上述情況下,是取代的NULL爲5/25和5/26與884(對於5/24的值),空爲6/1與889等

什麼不起作用:

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 
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。有些人不喜歡這種古怪的更新,但在這種情況下,確保它正常工作是微不足道的。

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 with Demo

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 

demo