2013-07-10 3 views
1

У меня есть интересная и конкретная проблема. Конкретно, потому что я не могу объяснить это просто, но я думаю, что это должно быть разумно легко решить. С учетом сказанного я не могу найти подобный вопрос, потому что я не знаю, как его искать!SQL split eggs в двух корзинах - чередование даты

В одной таблице, среди других столбцов, есть столбец даты с теми же самыми краткими записями, которые повторяются в течение года или около того в определенном шаблоне.

Например:

TermDate

  • 2013/07/16
  • 2013/07/16
  • 2013/07/16
  • 2013/07/23
  • 2013/07/23
  • 2013/07/23
  • 2013/07/23
  • 2013/07/30
  • 2013/07/30
  • 2013/07/30
  • 2013/07/30 ...

(каждый Вторник)

Мне нужно изменить эти даты по понедельникам и средам, так что '2013/07/16' станет «2013/07/15», '2013/07/23' будет тогда '' 2013/07/17 '', и '2013/07/30' будет следующим первым в наличии в понедельник - '2013/07/22' и т. Д.

Вы видите, что я имею в виду? Очевидно, для этого мне понадобился бы оператор CASE, но есть ли у кого-нибудь идея, как именно написать его?

Спасибо!

Я использую MS SQL SERVER, кстати!

+0

Вы спрашиваете, для перевода, округляется даты * вниз * к предыдущему понедельник или в среду, что наступит Скорейшее? 'Monday => Оставайтесь на месте. Вт => Понедельник. Weds => Оставайтесь такими же. Чт-воскресенье => Среда. Итак, все три записи 16 июня ВСЕ стали 15 июля? *** (Также, это MySQL, MS SQL Server, SQLite и т. Д.) *** – MatBailie

+1

Или, может быть, нет. Вы хотите перенести все записи с первой датой и округлите их до предыдущего понедельника или среды (которая станет * базовой датой * для последующих вычислений). Следующая группа записей с той же датой затем отображается в понедельник или среду сразу после * базовой даты *? А следующая группа или записи с той же картой даты со вторым понедельником или средой сразу после * базовой даты *? – MatBailie

+0

На этот раз все правильно! Я использую MS SQL, извините, я забыл добавить эту информацию! – gazdac

ответ

1

SQL округлить дату вплоть до начала недели ...

DATEADD(WEEK, DATEDIFF(WEEK, 0, <theDate>), 0) 

NOTE: This is NOT affected by your DATEFIRST environment setting. 


SQL условно вокруг него вниз в понедельник или среду ...

CASE WHEN DATEPART(DW, <theDate>) IN (3, 4, 5, 6, 7) THEN 
    DATEADD(WEEK, DATEDIFF(WEEK, 0, <theDate>), 0) 
ELSE 
    DATEADD(WEEK, DATEDIFF(WEEK, 0, <theDate>), 0) + 2 
END 

NOTE : DATEPART() _IS_ affected by your DATEFIRST environment setting. 
     This code has assumed SET DATEFIRST 7 


Затем вы можете поместить все свои записи в секцию uence. Если это позиция 1, вы добавляете два дня к базовой дате (понедельник => среда), если это позиция 2, вы добавляете семь дней (понедельник => в следующий понедельник), позиция три добавляет девять дней и т. Д.

Это упрощает до (position/2) * 7 + (position % 2) * 2 ...

position : (position/2) * 7 + (position % 2) * 2 
-------------------------------------------------- 
     0 : 0 
     1 : 2 
     2 : 7 
     3 : 9 
     4 : 14 
     5 : 16 
     6 : 21 

С запиской, что если ваша базовой даты случается быть средой, вам нужно лечить все ваши другие даты, как имеющие на одну позицию выше ...


Таким образом, я бы это сделать ...

SELECT 
    term_lookup.TermDate, 
    base_lookup.base_date 
    + ((term_lookup.term_id + base_lookup.base_id)/2) * 7 
    + ((term_lookup.term_id + base_lookup.base_id) % 2) * 2 AS new_date 
FROM 
(
    SELECT 
    DATEADD(WEEK, DATEDIFF(WEEK, 0, MIN(TermDate)), 0)     AS base_date, 
    CASE WHEN DATEPART(DW, MIN(TermDate)) IN (1, 2) THEN 0 ELSE 1 END AS base_id 
    FROM 
    yourTable 
) 
    AS base_lookup 
CROSS JOIN 
(
    SELECT 
    TermDate, 
    DENSE_RANK() OVER (ORDER BY TermDate) - 1 AS term_id 
    FROM 
    yourTable 
    GROUP BY 
    TermDate 
) 
    AS term_lookup 

Если что дает правильные результаты, присоединиться к ним обратно на данных, чтобы сделать и- бновить.

+0

Я сразу же буду вам благодарен и проверю, работает ли это позже! – gazdac

+0

Именно то, что я хотел сделать! Спасибо!!! – gazdac

0

попробовать это

UPDATE Table1 
SET TermDate = DATEADD(DAY, CASE DATEPART(weekday, TermDate) 
         WHEN 1 THEN 1 
         WHEN 2 THEN 0 
         WHEN 3 THEN 1 
         WHEN 4 THEN 0 
         WHEN 5 THEN 4 
         WHEN 6 THEN 3 
         WHEN 7 THEN 2 
        END, TermDate) 
+0

Серьезно? Вы читали какие-либо комментарии? Где я уже спрашивал, это то, что имел в виду ОП, а ОП сказал, что он что-то еще ... – MatBailie

+0

@MatBailie - Я не видел вашего вопроса. теперь я вижу, что я пропустил точку –