2010-07-22 7 views
0

J'ai une table comme ceci:Transformer le tableau en différentes Tableau

RowID | ProductDescription1 
----------------------------------------------------- 
1  | 0296620300-0296620399; 
2  | 0296620400-0296620499;0296620500-0296620599; 
3  | 0296620600-0296620699;0296620700-0296620799; 

Je veux devenir comme ceci:

NewRowID | Start  | End  | SourceRowID 
-------------------------------------------------- 
1  | 0296620300 | 0296620399 | 1 
2  | 0296620400 | 0296620499 | 2 
3  | 0296620500 | 0296620599 | 2 
4  | 0296620600 | 0296620699 | 3 
5  | 0296620700 | 0296620799 | 3 

Maintenant, j'ai une fonction qui peut faire des choses fractionnement quelle table retour:

ALTER FUNCTION [dbo].[ufn_stg_SplitString] 
(
    -- Add the parameters for the function here 
    @myString varchar(500), 
    @deliminator varchar(10) 
) 
RETURNS 
@ReturnTable TABLE 
(
    -- Add the column definitions for the TABLE variable here 
    [id] [int] IDENTITY(1,1) NOT NULL, 
    [part] [varchar](50) NULL 
) 
AS 
BEGIN 
     Declare @iSpaces int 
     Declare @part varchar(50) 

     --initialize spaces 
     Select @iSpaces = charindex(@deliminator,@myString,0) 
     While @iSpaces > 0 

     Begin 
      Select @part = substring(@myString,0,charindex(@deliminator,@myString,0)) 

      Insert Into @ReturnTable(part) 
      Select @part 

    Select @myString = substring(@mystring,charindex(@deliminator,@myString,0)+ len(@deliminator),len(@myString) - charindex(' ',@myString,0)) 


      Select @iSpaces = charindex(@deliminator,@myString,0) 
     end 

     If len(@myString) > 0 
      Insert Into @ReturnTable 
      Select @myString 

    RETURN 
END 

Je veux éviter d'utiliser le curseur si c'est possible.

Je suis apprécié votre commentaire/entrée.

+1

Je suppose que c'est un seul travail de migration, donc toute limitation sur son fonctionnement (par exemple "aucun curseur") devrait être arbitraire. –

+0

Quelle version de SQL Server? –

+1

Donc, vous avez besoin de normaliser les données, avoir la fonction de split pour le faire ... Pour quoi avez-vous besoin de nous? –

Répondre

2

Tout d'abord, cette solution nécessite SQL Server 2005+. Deuxièmement, en bas, j'offre une fonction Split séparée qui n'utilise pas de curseur. Troisièmement, voici une solution qui ne repose pas sur les valeurs étant d'une longueur spécifiée, mais plutôt que le séparateur est conforme:

Select Row_Number() Over (Order By Z.PairNum) As ItemNum 
    , Min(Case When Z.PositionNum = 1 Then Z.Value End) As [Start] 
    , Min(Case When Z.PositionNum = 2 Then Z.Value End) As [End] 
    , Z.RowId As SourceRowId 
From (
     Select T2.RowId, S.Value, T2.PairNum 
      , Row_Number() Over (Partition By T2.RowId, T2.PairNum Order By S.Value) As PositionNum 
     From (
       Select T.RowId, S.Value 
        , Row_Number() Over (Order By S.Value) As PairNum 
       From MyTable As T 
        Cross Apply dbo.Split(T.ProductDescription, ';') As S 
       ) As T2 
      Cross Apply dbo.Split(T2.Value, '-') As S 
     ) As Z 
Group By Z.RowId, Z.PairNum 

Et la fonction de Split:

Create FUNCTION [dbo].[Split] 
( 
    @DelimitedList nvarchar(max) 
    , @Delimiter nvarchar(2) = ',' 
) 
RETURNS TABLE 
AS 
RETURN 
    (
    With CorrectedList As 
     (
     Select Case When Left(@DelimitedList, Len(@Delimiter)) <> @Delimiter Then @Delimiter Else '' End 
      + @DelimitedList 
      + Case When Right(@DelimitedList, Len(@Delimiter)) <> @Delimiter Then @Delimiter Else '' End 
      As List 
      , Len(@Delimiter) As DelimiterLen 
     ) 
     , Numbers As 
     (
     Select TOP (Len(@DelimitedList)) Row_Number() Over (Order By c1.object_id) As Value 
     From sys.objects As c1 
      Cross Join sys.columns As c2 
     ) 
    Select CharIndex(@Delimiter, CL.list, N.Value) + CL.DelimiterLen As Position 
     , Substring (
        CL.List 
        , CharIndex(@Delimiter, CL.list, N.Value) + CL.DelimiterLen  
        , CharIndex(@Delimiter, CL.list, N.Value + 1)       
         - (CharIndex(@Delimiter, CL.list, N.Value) + CL.DelimiterLen) 
        ) As Value 
    From CorrectedList As CL 
     Cross Join Numbers As N 
    Where N.Value < Len(CL.List) 
     And Substring(CL.List, N.Value, CL.DelimiterLen) = @Delimiter 
    ) 
+0

Comme cette approche de non curseur approche – dcpartners

+0

Just thought ... cette fonction semble ne pas fonctionner avec '' (blank) comme délimiteur. Des idées? – dcpartners

+0

@ dewacorp.alliances - Il n'est pas nécessaire d'utiliser la fonction Split ci-dessus pour diviser chaque caractère. Vous pouvez le faire directement avec Substring et un CTE Numbers ou une table. – Thomas

2

SQL 2005/2008

with prods as 
(
select 1 as RowID, '0296620300-0296620399;' AS ProductDescription1 union all 
select 2 as RowID, '0296620400-0296620499;0296620500-0296620599;' AS ProductDescription1 union all 
select 3 as RowID, '0296620600-0296620699;0296620700-0296620799;' AS ProductDescription1 
) 

select 
ROW_NUMBER() OVER(ORDER BY RowId) as NewRowID, 
LEFT(Part,10) AS Start, /*Might need charindex if they are not always 10 characters*/ 
RIGHT(Part,10) AS [End], 
RowId as SourceRowID from prods 
cross apply [dbo].[ufn_stg_SplitString] (ProductDescription1,';') p 

Donne

NewRowID    Start  End  SourceRowID 
-------------------- ---------- ---------- ----------- 
1     0296620300 0296620399 1 
2     0296620400 0296620499 2 
3     0296620500 0296620599 2 
4     0296620600 0296620699 3 
5     0296620700 0296620799 3 
Questions connexes