2015-05-29 4 views
0

Я пытаюсь написать запрос, который изменяет диапазоны дат вокруг определенных интервалов. Он должен делать то, что выглядит как этотOverlapping Spans

Row Rank Begin Date End Date 
1  B  3/24/13  11/1/13 
2  A  10/30/13  4/9/15 
3  B  3/26/15  12/31/15 

и он стал

Row Rank Begin Date End Date 
1  B  3/24/13  10/29/13 
2  A  10/30/13  4/9/15 
3  B  4/10/15  12/31/15 

Чтобы объяснить далее, даты в строке 2 оценивается выше (A> B), поэтому даты в строке 1 и 3 должны измениться в течение дат в строке 2, чтобы избежать совпадений в датах.

Я использую SQL Server 2008 R2

+1

ли вы имеете в виду вы используете SQL Server? Пожалуйста, пометьте свой вопрос с помощью РСУБД. Кроме того, вы просто ищете помощь в слиянии дат или больше вопросов? Нужно ли понимать ваш рейтинг? –

+0

Да, я использую SQL Server 2008 R2. Я хочу обновить даты. И нет, нет никакого рейтинга в рейтинге, кроме A> B. И есть только A и B. Диапазоны дат с рангом A должны оставаться нетронутыми. – enigmaface

+0

Что делать, если у вас есть два последовательных '' B'' ранжированных отчета с перекрывающимися датами? –

ответ

0

Пожалуйста, используйте ниже запрос для обновления таблицы.

Update table_name 
set End_Date = DATEADD(day, -1, select Begin_Date from Table_name where 
Row_number = '2') 
where row = 1; 

Нужно менять номера строк каждый раз, когда вы запускаете запрос. Дайте мне знать. Если это сработает для вас.

Я предлагаю Сначала создать View

CREATE OR REPLACE VIEW tempview AS 
SELECT row, begin_date FROM table_name 
WHERE row > 1; 

Затем Используйте этот запрос, чтобы обновить все строки. Если не удается обновить только первую строку.

Update table_name 
set End_Date = DATEADD(day, -1, select Begin_Date from tempview) 

Надеется, что это работает

+0

Спасибо, это работает. Однако я хочу применить это к очень большому набору данных (700 строк), поэтому я бы хотел, чтобы что-то более автоматизированное. – enigmaface

+0

Пожалуйста, проверьте обновления –

0

Вы можете использовать следующий запрос:

;WITH CTE AS (
    SELECT Row, Rank, BeginDate, EndDate, 
      ROW_NUMBER() OVER (ORDER BY BeginDate) AS rn 
    FROM mytable 
), ToUpdate AS (
    SELECT c1.Row, c1.Rank, c1.BeginDate, c1.EndDate, 
      c2.Rank AS pRank, c2.EndDate AS pEndDate, 
      c3.Rank AS nRank, c3.BeginDate AS nBeginDate 
    FROM CTE AS c1 
    LEFT JOIN CTE AS c2 ON c1.rn = c2.rn + 1 
    LEFT JOIN CTE AS c3 ON c1.rn = c3.rn - 1 
    WHERE c1.Rank = 'B' 
) 
UPDATE ToUpdate 
SET BeginDate = CASE 
        WHEN pEndDate IS NULL 
         THEN BeginDate 
        WHEN (pEndDate >= BeginDate) AND (pRank = 'A') 
         THEN DATEADD(d, 1, pEndDate) 
        ELSE BeginDate 
       END, 
    EndDate = CASE 
        WHEN nBeginDate IS NULL 
         THEN EndDate 
        WHEN (nBeginDate <= EndDate) AND (nRank = 'A') 
         THEN DATEADD(d, -1, nBeginDate) 
        ELSE EndDate 
       END 

CTE изначально построен для назначения последовательного, восходящий номера для каждой записи Вашего стола. ROW_NUMBER() Функция окна используется для этой цели.

В качестве основы мы строим ToUpdate. Этот последний CTE содержит значения даты текущие, а также предыдущие и следующий записей. Это LEFT JOIN:

LEFT JOIN CTE AS c2 ON c1.rn = c2.rn + 1 

используется для соединения вместе с предыдущей записи, в то время как этот:

LEFT JOIN CTE AS c3 ON c1.rn = c3.rn - 1 

используется для соединения вместе с следующей записи.

Используя выражения CASE, мы теперь можем легко идентифицировать перекрытия и, если они есть, выполнить обновление.

Demo here