2010-11-26 12 views
2

日付の列にUNIQUEキーを持つデータベーステーブルがあるため、日付ごとに複数の行が存在することはありません。すでにデータベースに存在する1日分の新しい行を挿入すると、それ以降のすべての連続した日付を「無料」になるまで1日前に戻したいと思います。ここで再帰的な「重複キー更新」

は、私が考えたものだ:

INSERT INTO 
`activity` 
(`name`,`date`) 
VALUES 
('date 7','2009-07-31') 
ON DUPLICATE KEY 
UPDATE `date` = DATE_ADD(`date`, INTERVAL '1' DAY) 

私の考えはON DUPLICATE KEY UPDATE意志バブルアップテーブルをすることを、それが存在しない日に達するまで、すべての日付に1日を追加し続けるです。私のテーブルの内容は、次のようになります場合

例えば:

date 1, 2009-07-30 
date 2, 2009-07-31 
date 3, 2009-08-01 
date 4, 2009-08-02 
date 5, 2009-08-04 <- notice this date is two days past the previous one 

...と私は2009年7月31日に「日7 'を挿入するために行く、私はそれがこれを行うにはしたいと思います

date 1, 2009-07-30 
date 7, 2009-07-31 <- newly inserted row 
date 2, 2009-08-01 <- this and subsequent rows are all incremented 
         by one day until it hits a non-consecutive day 
date 3, 2009-08-02 
date 4, 2009-08-03 
date 5, 2009-08-04 <- notice this date hasn't changed 

重複キーの更新では、そのようには機能しません。ただし、重複している行のみが更新され、異なる行で重複すると重複キーエラーが発生します。

SQLだけでこの効果を実現するスマートな方法はありますか?

答えて

2

対象日付以降の最初の空き時間を照会します。これには、テーブル内に後継者がない日付を見つけるための左自己結合が含まれます。

SELECT DATE_ADD(Min(a.`date`), INTERVAL '1' DAY) AS `free_date` 
FROM `activity` a 
LEFT JOIN `activity` z 
ON z.`date` = DATE_ADD(a.`date`, INTERVAL '1' DAY) 
WHERE z.`date` IS NULL 
AND a.`date` >= '2009-07-31' 

更新を実行して、ターゲット日付と最初の空き日付の間の各日付を増分します。

ここにあなたの希望する挿入の余地があります。

+0

ON

をINNER JOIN。 –

+0

@Lieven:検索するレコードは、後続の日付が見つからないレコードなので、左結合でなければなりません。 – Narveson

+0

申し訳ありませんが、遅れています。私は入力を続けていますが、私の脳はすでに停止しています。 –

0

その後、最大の1日のような

何か追加、更新を行う前に、最大の日付を選択:私はあなたにLEFTを変更する必要があると信じてDUPLICATE KEY

UPDATE `date` = DATE_ADD(select max('date') from 'activity', INTERVAL '1' DAY)