У меня есть довольно сомнительные данные, на которые я смотрю, и мне было поручено выяснить, сколько месяцев подряд что-то происходит.Однако я заметил, что в некоторых из моих справочных таблиц отдельные значения даты неправильно закодированы, и если в одном месяце есть несколько значений, самое последнее следует добавить в следующий месяц.
Например:
Contact _id | Original Payment Date
id001 | 02/07/2003
id001 | 30/07/2003 --should be changed to 30/08/2003
id001 | 01/09/2003
id001 | 01/10/2003
id001 | 30/10/2003 -- should be changed to 30/11/2003
id001 | 02/12/2003
id001 | 31/12/2003 -- should be changed to 31/01/2004
id001 | 30/01/2004
id001 | 03/03/2004
Однако при простой функции DATEADD я нахожу две проблемы:
1) Если платеж необходимо перенести в следующий месяц, и его дата больше, чем в следующем, позволяет(то есть 31.01.2003 не может перейти к 31.02.2003) Я не уверен, как dateadd будет работать в этом случае
2) Если в приведенном выше примере я внесу эти изменения, у нас естьследующие данные:
id001 | 02/07/2003
id001 | 30/08/2003
id001 | 01/09/2003
id001 | 01/10/2003
id001 | 30/11/2003
id001 | 02/12/2003
id001 | 31/01/2004 --This should now be changed to a value in Februrary 2004 as there are
now duplicates in January 2004 created by the previous amendment
id001 | 30/01/2004
id001 | 03/03/2004
Хотя я полагаю, что 2 «цикла» изменений позволят убедиться, что все данные верны, я не уверен, и поэтому мне очень хотелось бы, чтобы какой-то способ подтолкнуть последнюю дату вмесяц (где для этого месяца 2 значения) переслать месяц, который повторяется до тех пор, пока по возможности больше не будет дубликатов.
Я использую sql server 2005 и справочную таблицу hоколо 20 миллионов строк, поэтому я бы предпочел не использовать курсоры, если это возможно:)
Спасибо!
update Скрипт, который я использую для обновления датпервый раз это:
;WITH cte1 AS (
SELECT contact_id
,value_net
,DATEPART(YEAR, date_received)*12 + DATEPART(MONTH, date_received) -
DENSE_RANK() OVER
(PARTITION BY contact_id
ORDER BY DATEPART(YEAR, date_received)*12 + DATEPART(MONTH, date_received)) AS dategroup
,DENSE_RANK() OVER
(PARTITION BY contact_id
ORDER BY DATEPART(YEAR, date_received)*12 + DATEPART(MONTH, date_received)) AS rnk
,ROW_NUMBER() OVER
(PARTITION BY contact_id
ORDER BY DATEPART(YEAR, date_received)*12 + DATEPART(MONTH, date_received)) AS rnk2
,date_received
FROM donation with (nolock)
WHERE contact_id IS NOT NULL
)
,cte2 AS
(
SELECT
c1.contact_id
,c1.value_net
,c1.dategroup
,CASE WHEN c1.rnk = c2.rnk AND c1.rnk2 > c2.rnk2 THEN DATEADD(MM,+1,c1.date_received) ELSE c1.date_received END as date_received
from cte1 c1
LEFT OUTER JOIN cte1 c2 WITH (nolock) ON c2.contact_id = c1.contact_id AND c2.rnk = c1.rnk AND c2.rnk2 = c1.rnk2-1
)