2017-05-15 2 views
0

Meine Tabelle hat drei Zeilen:Wie jede Zeile in mehrere Zeilen aufgeteilt

ID MULTI_CODES 
1 10-101-102 
2 20-201-202 
3 30-301-302 

Wie eine Erklärung schreiben jede Zeile wie diese unter Berücksichtigung begrenzt Code aufzuspalten

ID SINGLE_CODE LEVEL 
1 10    1 
1 101    2 
1 102    3 

2 20    1 
2 201    2 
2 202    3 

3 30    1 
3 301    2 
3 302    3 
+3

Ich schlage vor, uns zu zeigen, was Sie versucht haben. Werfen Sie auch einen Blick auf [how to ask] (https://stackoverflow.com/help/how-to-ask), um eine qualitativ hochwertige Frage zu stellen, die höhere Chancen auf eine schnelle und genaue Antwort bietet. Vielen Dank. –

+0

String Split und Pivot? –

+0

welche Version von SQL Server? –

Antwort

2

Wenn Sie auf SQL sind Server 2016 können Sie die eingebaute string_split Funktion verwenden.

Wenn nicht, benötigen Sie Ihre eigene Funktion. Eine, die sehr gut funktioniert, ist Jeff Modens tally table method. Meine veränderte Version dieser sieht wie folgt aus, so dass für den Benutzer angegebenen Trennzeichen und bei Bedarf bestimmte Werte:

create function dbo.StringSplit 
(
    @str nvarchar(4000) = ' '    -- String to split. 
    ,@delimiter as nvarchar(1) = ','  -- Delimiting value to split on. 
    ,@num as int = null      -- Which value to return. 
) 
returns table 
as 
return 
(
         -- Start tally table with 10 rows. 
    with n(n) as (select n from (values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) n(n)) 
         -- Select the same number of rows as characters in isnull(@str,'') as incremental row numbers. 
        -- Cross joins increase exponentially to a max possible 10,000 rows to cover largest isnull(@str,'') length. 
     ,t(t) as (select top (select len(isnull(@str,'')) a) row_number() over (order by (select null)) from n n1,n n2,n n3,n n4) 
          -- Return the position of every value that follows the specified delimiter. 
     ,s(s) as (select 1 union all select t+1 from t where substring(isnull(@str,''),t,1) = @delimiter) 
          -- Return the start and length of every value, to use in the SUBSTRING function. 
        -- ISNULL/NULLIF combo handles the last value where there is no delimiter at the end of the string. 
     ,l(s,l) as (select s,isnull(nullif(charindex(@delimiter,isnull(@str,''),s),0)-s,4000) from s) 
    select rn as ItemNumber 
      ,Item 
    from(select row_number() over(order by s) as rn 
       ,substring(isnull(@str,''),s,l) as item 
     from l 
     ) a 
    where rn = @num  -- Return a specific value where specified, 
     or @num is null -- Or everything where not. 
) 
go 

und wird wie folgt verwendet:

declare @t table (ID int, MULTI_CODES nvarchar(50)); 
insert into @t values (1,'10-101-102'),(2,'20-201-202'),(3,'30-301-302'); 

select t.ID 
     ,t.MULTI_CODES 
     ,s.Item as SINGLE_CODE 
     ,s.ItemNumber as [Level] 
from @t t 
    outer apply dbo.StringSplit(t.MULTI_CODES,'-',null) s 
order by t.ID 
     ,s.ItemNumber; 

Welche Ausgänge:

+----+-------------+-------------+-------+ 
| ID | MULTI_CODES | SINGLE_CODE | Level | 
+----+-------------+-------------+-------+ 
| 1 | 10-101-102 |   10 |  1 | 
| 1 | 10-101-102 |   101 |  2 | 
| 1 | 10-101-102 |   102 |  3 | 
| 2 | 20-201-202 |   20 |  1 | 
| 2 | 20-201-202 |   201 |  2 | 
| 2 | 20-201-202 |   202 |  3 | 
| 3 | 30-301-302 |   30 |  1 | 
| 3 | 30-301-302 |   301 |  2 | 
| 3 | 30-301-302 |   302 |  3 | 
+----+-------------+-------------+-------+ 
+1

WOWW !!!! vielen dank für diese tolle und schnelle antwort !!! – Haseeb

+2

Wenn Sie dies zu einer einzigen Aussage gemacht haben, würde es die Leistung unterstützen. Es gibt wirklich keine Notwendigkeit für Variablen und solche hier. Nur der Cte Stack mit dem Final und es würde sich von einer Multi-Statement-Tabelle zu einer Inline-Funktion ändern. –

+0

@SeanLange Richtig du bist, das ist es, was du bekommst, wenn du in deiner Entwicklungsumgebung herumpinkst und nicht nach dir selbst reinigst. Antwort aktualisiert – iamdave

0

Sie können die Funktion cross apply für string_split verwenden

select id, Value as Single_code, RowN as [Level] from #yourcodes cross apply 
( 
    select RowN= row_number() over (order by (select null)), value 
    from string_split(Multi_codes, '-') 
) a 
Output

:

+----+-------------+-------+ 
| id | Single_code | Level | 
+----+-------------+-------+ 
| 1 |   10 |  1 | 
| 1 |   101 |  2 | 
| 1 |   102 |  3 | 
| 2 |   20 |  1 | 
| 2 |   201 |  2 | 
| 2 |   202 |  3 | 
| 3 |   30 |  1 | 
| 3 |   301 |  2 | 
| 3 |   302 |  3 | 
+----+-------------+-------+ 
+0

danke auch funktioniert gut – Haseeb

2
IF OBJECT_ID('tempdb..#TEMPtable') IS NOT NULL 
Drop table #TEMPtable 
;With cte(ID, MULTI_CODES) 
AS 
(
select 1,'10-101-102' UNION ALL 
select 2,'20-201-202' UNION ALL 
select 3,'30-301-302' 
) 
SELECT * INTO #TEMPtable FROM cte 


SELECT ID, Split.a.value('.','Varchar(100)') AS MULTI_CODES,ROW_NUMBER()Over(Partition by ID Order by ID) AS LEVEL 
FROM(

SELECT ID, CASt('<M>' + Replace(MULTI_CODES,'-','</M><M>') +'</M>' AS XML)As MULTI_CODES 

FROM #TEMPtable 
)AS A 
CROSS APPLY 
MULTI_CODES.nodes('/M') AS Split(A) 

OutPut

ID MULTI_CODES LEVEL 
---------------------- 
1 10   1 
1 101   2 
1 102   3 
2 20   1 
2 201   2 
2 202   3 
3 30   1 
3 301   2 
3 302   3 
+0

danke das funktioniert auch gut !!!!! – Haseeb

Verwandte Themen