2016-07-24 4 views
0

Ищу SQL-запрос, который будет принимать следующие табличные данные в качестве входных данныхSplit логики в SQL

ID Start date end date 

ID1 01.01.2016 31.12.2016 

ID2 01.02.2016 30.06.2016 

ID3 01.10.2016 31.10.2016 

ID4 01.02.2016 31.07.2016 

и дает следующий вывод

ID1 01.01.2016 31.01.2016 

ID4 01.02.2016 31.07.2016 

ID1 01.08.2016 30.09.2016 

ID3 01.10.2016 31.10.2016 

ID1 01.11.2016 31.12.2016 

смотрите, что ID1 расщепляется только для один месяц, поскольку ID2, ID3 и ID4 имеют перекрытие с ID1. Идея - это самый последний диапазон дат. если вы видите, что вывод ID2 полностью отклонен, поскольку он перезаписывается ID4.

, пожалуйста, разместите подсказки по запросу.

+1

Я не вижу кода, показывающего ваши попытки? Пожалуйста, поделитесь кодом и просмотрите следующие [Как создать минимальный, полный и проверенный пример] (http://stackoverflow.com/help/mcve). Кроме того, ваш _tags_, который вы использовали, для какой СУБД вам нужен этот запрос? Теги в StackOverflow не похожи на хэштеги в социальных сетях - добавив больше, не означает, что вы получите больше ответов на свой вопрос. Удалите те, которые не применяются. –

+0

ID1 - это начальный план, а ID2 - это изменение (или обновление ID1) и т. Д., Поэтому таблица плана, которая является входом, содержит все изменения в плане планов с идентификаторами. с внесенными изменениями я хотел бы видеть перекрывающиеся диапазоны дат, которые могут аннулировать предыдущий план, а также разделить записи, как показано в выходном результате. извините за меньшее объяснение – talk2raghurao

+0

обновите свой вопрос с помощью информации о схеме и запросах sql, которые вы использовали для получения результата. –

ответ

0

Я придумал некоторую логику для этого. Я могу дать синтаксис для sql-сервера (но вам нужно будет найти синтаксис для mysql). Замените [Имя таблицы] на имя вашей таблицы в следующих ниже запросах.

Получить максимальную дату окончания из таблицы и хранить в переменной:

declare @max_end_date datetime 
set @max_end_date = (select max([end date]) from [Table Name]) 

Collect возможные даты начала во временную таблицу, добавив в номер строки и две пустые колонки (» 'в качестве идентификатора, 0 а боян):

select 
    row_number()over(order by start_date) as row, 
    start_date, 
    '' as id, 
    0 as dupe 
into #temp 
from 
    (select [start date] as start_date 
    from [Table Name] 
    union 
    select dateadd(day,1,[end date]) 
    from [Table Name] 
    where [end date] <> @max_end_date) 
group by start_date 

Обновление каждой строки временной таблицы с планом эффективным на этой начальной даты:

update #temp 
set #temp.id = c.id 
from #temp 
left outer join 
    (select a.start_date, max(b.id) as id 
    from #temp a 
    inner join [Table Name] b 
    on a.start_date between b.[start date] and b.[end date] 
    group by a.start_date) c 
on #temp.start_date = c.start_date 

Update временная таблица с флагом разметить 'дубликат' строки:

update #temp 
set #temp.dupe = 1 
from #temp 
inner join #temp b 
on a.row = b.row + 1 
and a.id = b.id 

Удалить повторяющиеся строки:

delete from #temp where dupe = 1 

Обновить столбец строки:

update #temp 
set row = row_number()over(order by start_date) 

Присоединиться к этой таблицу для себя, чтобы создать таблицу после:

select 
    a.id as id, 
    a.start_date as start_date, 
    isnull(dateadd(day,-1,b.start_date),@max_end_date) as end_date 
from #temp a 
left outer join #temp b 
    on a.row = b.row - 1 
+0

Учитывая, что я потратил много времени на это решение в отчаянной попытке получить какую-то репутацию, чтобы в свою очередь привлечь некоторых моих охотников за головами, я решил адаптировать этот код к Postgres, чтобы убедиться, что он сработал. За исключением одной недостающей строки в коде (теперь она добавлена ​​в решение выше), это произошло. –

+0

Спасибо @vorpulus. я проверю и вернусь – talk2raghurao