Я искал, но не могу найти решение следующей проблемы.
У меня есть несколько прайс-листов с парой миллионов строк, и я нашел много примеров, которые можно объединить в одну строку, потому что даты начала и окончания группы являются последовательными (enddate: 20151231, next startdate: 20160101)
Но я также обнаружил много пробелов, что означает, что прямой подход с использованием функций min () и max () неприменим, поскольку возможные пробелы будут проигнорированы.
Следующее содержит таблицу #Prices с примерами записей и таблицу #Target с результатом, для которого я стремлюсь:
Спасибо.
Мое определение разрыва - это когда между двумя последовательными записями больше одного дня.
if object_id('tempdb..#Prices', 'table') is not null
drop table #Prices
;
create table #Prices (
Product varchar(50) not null
, Value decimal(18,5) not null
, ValidFrom date not null
, ValidTo date null
)
insert into #Prices
(
Product
, Value
, ValidFrom
, ValidTo
)
select
Product = 'Island A'
, Value = 10.10
, ValidFrom = '20140101'
, ValidTo = '20140606'
union all
select
Product = 'Island A'
, Value = 10.10
, ValidFrom = '20140607'
, ValidTo = '20141010'
union all
select
Product = 'Island A'
, Value = 10.11
, ValidFrom = '20141011'
, ValidTo = '20141231'
union all
select
Product = 'Island A'
, Value = 11.10
, ValidFrom = '20150101'
, ValidTo = '20151231'
union all
select
Product = 'Island A'
, Value = 10.10
, ValidFrom = '20160101'
, ValidTo = null
union all
select
Product = 'Gap B'
, Value = 20.10
, ValidFrom = '20140101'
, ValidTo = '20140606'
union all
select
Product = 'Gap B'
, Value = 20.10
, ValidFrom = '20140607'
, ValidTo = '20141010'
union all
select
Product = 'Gap B'
, Value = 20.10
, ValidFrom = '20150101'
, ValidTo = '20151231'
union all
select
Product = 'Gap B'
, Value = 20.10
, ValidFrom = '20160101'
, ValidTo = null
select *
from #Prices as P
order by P.Product, P.ValidFrom
;
if object_id('tempdb..#Target', 'table') is not null
drop table #Target
;
create table #Target (
Product varchar(50) not null
, Value decimal(18,5) not null
, ValidFrom date not null
, ValidTo date null
)
insert into #Target
(
Product
, Value
, ValidFrom
, ValidTo
)
select
Product = 'Island A'
, Value = 10.10
, ValidFrom = '20140101'
, ValidTo = '20141010'
union all
select
Product = 'Island A'
, Value = 10.11
, ValidFrom = '20141011'
, ValidTo = '20141231'
union all
select
Product = 'Island A'
, Value = 11.10
, ValidFrom = '20150101'
, ValidTo = '20151231'
union all
select
Product = 'Island A'
, Value = 10.10
, ValidFrom = '20160101'
, ValidTo = null
union all
select
Product = 'Gap B'
, Value = 20.10
, ValidFrom = '20140101'
, ValidTo = '20141010'
union all
select
Product = 'Gap B'
, Value = 20.10
, ValidFrom = '20150101'
, ValidTo = null
select *
from #Target as P
order by P.Product, P.ValidFrom
;
ИЗМЕНИТЬ. Надеюсь, что это изменение - ответ на ваш вопрос. Последовательные записи (максимум 1 день между записями) можно агрегировать, взяв минимальное (ValidFrom) и максимальное (ValidTo). проблема в промежутках, они будут проигнорированы. Результатом для продукта «Разрыв B» будет одна запись. Любое попадание в эту запись с Date получит значение 20.10, даже если дата находится в периоде Gap.
Gap B | 20.10 | 20140101 | null
Поэтому мне нужны 2 записи, поэтому все объединения в таблице приведут к правильному значению и отсутствию значения в периоде разрыва.
Gap B | 20.10 | 20140101 | 20141010
Gap B | 20.10 | 20151231 | null