Это довольно типичная проблема с поиском дальности с включенной конкатенацией. Не уверен, что следующее соответствует точно, но это отправная точка. (Курсоры обычно лучше избегать, за исключением небольшого набора случаев, когда они быстрее, чем решения на основе набора, поэтому перед тем, как нападающие курсора пойдут на меня, обратите внимание, что я использую курсор здесь специально, потому что это пахнет мне, как удобный для курсора . проблема - я обычно их избежать)
Так что, если я создаю такие данные:
CREATE TABLE [dbo].[sourceValues](
[Start] [int] NOT NULL,
[End] [int] NOT NULL,
[Item] [varchar](100) NOT NULL
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[sourceValues] WITH CHECK ADD CONSTRAINT [End_after_Start] CHECK (([End]>[Start]))
GO
ALTER TABLE [dbo].[sourceValues] CHECK CONSTRAINT [End_after_Start]
GO
declare @i int; set @i = 0;
declare @start int;
declare @end int;
declare @item varchar(100);
while @i < 1000
begin
set @start = ABS(CHECKSUM(newid()) % 100) + 1 ; -- "random" int
set @end = @start + (ABS(CHECKSUM(newid()) % 10)) + 2; -- bigger random int
set @item = char((ABS(CHECKSUM(newid())) % 5) + 65); -- random letter A-E
print @start; print @end; print @item;
insert into sourceValues(Start, [End], Item) values (@start , @end, @item);
set @i += 1;
end
Тогда я могу относиться к проблеме так: каждый «Пуск» и каждый «End» значение представляет собой изменение в коллекции текущих элементов, либо добавив один, либо удалив один из них в определенное время. В приведенном ниже коде я называю это «событие», что означает «Добавить или удалить». Каждое начало или конец похоже на время, поэтому я использую термин «тик». Если я создаю коллекцию всех событий, упорядоченных по времени события (начало и конец), я могу выполнить итерацию, сохраняя при этом текущую таблицу в таблице памяти всех элементов, которые находятся в игре. Каждый раз, когда изменяется значение клеща, я беру снимок этой бирки:
declare @tick int;
declare @lastTick int;
declare @event varchar(100);
declare @item varchar(100);
declare @concatList varchar(max);
declare @currentItemsList table (Item varchar(100));
create table #result (Start int, [End] int, Items varchar(max));
declare eventsCursor CURSOR FAST_FORWARD for
select tick, [event], item from (
select start as tick, 'Add' as [event], item from sourceValues as adds
union all
select [end] as tick, 'Remove' as [event], item from sourceValues as removes
) as [events]
order by tick
set @lastTick = 1
open eventsCursor
fetch next from eventsCursor into @tick, @event, @item
while @@FETCH_STATUS = 0
BEGIN
if @tick != @lastTick
begin
set @concatList = ''
select @concatList = @concatlist + case when len(@concatlist) > 0 then '-' else '' end + Item
from @currentItemsList
insert into #result (Start, [End], Items) values (@lastTick, @tick, @concatList)
end
if @event = 'Add' insert into @currentItemsList (Item) values (@item);
else if @event = 'Remove' delete top (1) from @currentItemsList where Item = @item;
set @lastTick = @tick;
fetch next from eventsCursor into @tick, @event, @item;
END
close eventsCursor
deallocate eventsCursor
select * from #result order by start
drop table #result
Используя курсор для этого особого случая позволяет только один «проход» по данным, как проблема текущих итогов. У Ицика Бен-Гана есть отличные примеры этого в его книгах по SQL 2005.
Какую версию SQL Server вы используете? – Sung
Сколько предметов может пересекаться? (т. е. это всегда 2, a и b, или это может быть любое число?) – onupdatecascade
SQL Server 2008, а количество элементов, наложенных на них, может быть любым – river0