Il s'agit d'un problème de télémétrie assez typique, avec la concaténation lancée. Vous ne savez pas si ce qui suit correspond exactement, mais c'est un point de départ. (Les curseurs sont généralement mieux évités sauf dans le petit ensemble de cas où ils sont plus rapides que les solutions basées sur les ensembles, donc avant que les ennemis du curseur ne m'atteignent, veuillez noter que j'utilise un curseur ici parce que cela me semble . problème - je les évite généralement)
donc, si je crée des données comme ceci:
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
Ensuite, je peux traiter le problème comme ceci: chaque « Démarrer » et chaque valeur « End » représente un changement dans la collection d'éléments actuels, en ajoutant ou en supprimant un, à un moment donné. Dans le code ci-dessous, j'alias cette notion comme "événement", ce qui signifie un ajout ou un retrait. Chaque début ou fin est comme un temps, donc j'utilise le terme «tick». Si je fais une collection de tous les événements, classés par événement (Début ET Fin), je peux parcourir la liste tout en gardant un pointage dans une table en mémoire de tous les éléments en jeu. Chaque fois que la valeur tiques changements, je prends un aperçu de ce décompte:
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
l'aide d'un curseur pour ce cas particulier ne permet qu'un seul « passer » à travers les données, comme un problème de cumuls. Itzik Ben-Gan en a d'excellents exemples dans ses livres SQL 2005.
Quelle version de SQL Server utilisez-vous? – Sung
Combien d'éléments peuvent se chevaucher? (c'est à dire toujours 2, a et b, ou pourrait-il être un nombre quelconque?) – onupdatecascade
SQL Server 2008, et le nombre d'éléments superposés peut être n'importe qui – river0