0
votes

Différence entre deux colonnes en lignes séparées pour chaque valeur entre les deux

J'ai du mal à expliquer mon problème mais j'ai ce tableau

ID  NUMBER
1   10
1   11
1   12
2   30
2   31
3   11
3   12
3   13

et je veux quelque chose comme ceci:

ID  START   END
1   10      12
2   30      31
3   11      13

J'ai besoin tous les nombres entiers uniques entre les deux colonnes se transforment en lignes séparées.

Voici à quoi je veux que la transformation ressemble

Je n'ai rien essayé car je ne sais même pas comment appeler une telle procédure, donc toute aide est appréciée


0 commentaires

3 Réponses :


2
votes

Si vous n'avez pas de tableau de nombres (fortement recommandé), vous pouvez utiliser un tableau de pointage ad hoc de concert avec un CROSS APPLY

Exemple

ID  Number
1   10
1   11
1   12
2   30
2   31
3   11
3   12
3   13

Select A.ID
      ,B.Number 
 From  YourTable A
 Cross Apply ( Select Top ([End]-[Start]+1) 
                      Number=[START]-1+Row_Number() Over (Order By (Select NULL)) 
                From  master..spt_values n1, master..spt_values n2 
             ) B


3 commentaires

NB. CROSS APPLY est parfois appelé LATERAL JOIN (sur d'autres plates-formes.)


@Hogan "NB" Je n'ai pas vu ça depuis un certain temps. Me ramène à l'angoisse de mes cours de latin. :)


John: ipso facto - je suppose que je vieillis.



-1
votes

--create table NewTable
--(
--ID int,
--NUMBER int
--)

DECLARE @ID nvarchar(50) 
declare @START int
declare @END int

DECLARE Cursor_Name CURSOR 
FOR 
    select ID, [START], [End] from tblSequences
    OPEN Cursor_Name
    FETCH NEXT FROM Cursor_Name    INTO  @ID,@START,@END
    WHILE @@FETCH_STATUS = 0
    begin

    WHILE @START<=@END
    begin
        insert into NewTable (ID, NUMBER) Values (@ID, @START)
        set @START = @START+1
    end

FETCH NEXT FROM Cursor_Name INTO  @ID,@START,@END
end 

CLOSE Cursor_Name
DEALLOCATE Cursor_Name

sélectionnez * dans NewTable


2 commentaires

Les curseurs sont toujours une mauvaise idée en SQL


@Hogan, oui, j'ai accepté, car actuellement j'ai proposé une solution, le cas échéant, puis peut être utilisée. Merci



1
votes

Dans SQL Server, vous pouvez utiliser un CTE récursif:

with cte as (
      select id, [start] as number, [end] as end_number
      from t
      union all
      select id, number + 1
      from cte
      where number < end_number
     )
select id, number
from cte;

Remarque: Si la plage peut dépasser 100, vous avez besoin de l'option (maxrecursion) pour la requête .

Les CTE récursifs sont généralement un peu plus lents qu'une table de nombres. Cependant, je les trouve beaucoup plus rapides que ce à quoi je m'attendais.


0 commentaires