我有一段看起来像这样的代码
declare @t table (record int,string varchar(MAX))
insert into @t (record,string)values (1,'ABC')
insert into @t (record,string)values (2,'DEF/123')
insert into @t (record,string)values (3,'GHI/456/XYZ')
我得到一个查询,我可以这样结果
SELECT record,
RIGHT(LEFT(T.string,Number-1),CHARINDEX('/',REVERSE(LEFT('/' + T.string,number-1))))
FROM
master..spt_values,
@t T
WHERE
Type = 'P' AND Number BETWEEN 1 AND LEN(T.string)+1
AND
(SUBSTRING(T.string,Number,1) = '/' OR SUBSTRING(T.string,Number,1) = '')
获得输出
record values
1 ABC
2 DEF
2 123
3 GHI
3 456
3 XYZ
我怎样才能获得像这样的输出
record values
1 ABC
1 NULL
1 NULL
2 DEF
2 123
2 NULL
3 GHI
3 456
3 XYZ
一些用户已经问过了。我在这里表现得很好,从那里我如何实现欲望输出
答案 0 :(得分:0)
我们的想法是生成一行record
交叉加入1,2,3
,以生成record
与另一列编号为1,2,3
的组合,然后使用该组合加入你的分裂价值。您必须先为分割值添加ROW_NUMBER
,才能将其与生成的组合一起加入。
;WITH CteThree(record, N) AS(
SELECT
t.record,
x.N
FROM (
SELECT DISTINCT record FROM @t
)t
CROSS JOIN(
SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3
)x(N)
),
CteSplitted AS(
SELECT
record,
ROW_NUMBER() OVER(PARTITION BY record ORDER BY Number) AS N,
RIGHT(LEFT(T.string,Number-1),CHARINDEX('/',REVERSE(LEFT('/' + T.string,number-1)))) AS str
FROM master..spt_values v
CROSS JOIN @t T
WHERE
Type = 'P'
AND Number BETWEEN 1 AND LEN(T.string)+1
AND (SUBSTRING(T.string,Number,1) = '/' OR SUBSTRING(T.string,Number,1) = '')
)
SELECT
t.record,
s.str
FROM CteThree t
LEFT JOIN CteSplitted s
ON s.record = t.record
AND s.N = t.N
答案 1 :(得分:0)
怎么样:
declare @t table (record int,string varchar(MAX));
declare @s char(1) = '/';
WITH counter as (
SELECT MAX(LEN(string)-LEN(REPLACE(string, @s, ''))) lines
) ,
splitter as (
SELECT record, string
, line = 1
, pos = h.pos
, value = CASE WHEN h.pos>0 THEN SUBSTRING(string,1,h.pos) ELSE string END
FROM @t
CROSS APPLY (SELECT CHARINDEX(@s, string) pos ) h
UNION ALL
SELECT record, string
, line = s.line + 1
, pos = CASE WHEN s.pos = 0 THEN 0 ELSE h.pos END
, value = CASE WHEN s.pos = 0 THEN null
WHEN h.pos > 0 THEN SUBSTRING(string,s.pos+1,h.pos-s.pos-1)
ELSE SUBSTRING(string,s.pos+1,99)
END
FROM splitter s
CROSS APPLY (SELECT CHARINDEX(@s, string, s.pos+1) pos ) h
WHERE s.line<=(SELECT lines FROM counter)
)
SELECT *
FROM splitter
ORDER BY record,line
答案 2 :(得分:0)
试试这个
DECLARE @t TABLE
(
record INT ,
string VARCHAR(MAX)
)
INSERT INTO @t
( record, string )
VALUES ( 1, 'ABC' ),
( 2, 'DEF/123' ),
( 3, 'GHI/456/XYZ' );
WITH cte
AS ( SELECT Number = 1
UNION ALL
SELECT Number + 1
FROM cte
WHERE Number <= 100
),
NotNull
AS ( SELECT record ,
RIGHT(LEFT(T.string, Number - 1),
CHARINDEX('/',
REVERSE(LEFT('/' + T.string,
number - 1)))) string ,
ROW_NUMBER() OVER ( PARTITION BY T.record ORDER BY T.record ) AS RN
FROM cte
JOIN @t T ON Number <= ( LEN(T.string) + 1 )
AND SUBSTRING(T.string + '/', Number, 1) = '/'
)
SELECT template.record ,
NotNull.string
FROM ( SELECT *
FROM ( SELECT DISTINCT
RN
FROM NotNull
) AS A
CROSS JOIN ( SELECT Record
FROM NotNull
) AS B
) AS template
LEFT JOIN NotNull ON template.RN = NotNull.RN
AND template.Record = NotNull.Record
答案 3 :(得分:0)
试试这个
declare @t table (record int,string varchar(MAX))
insert into @t (record,string)values (1,'ABC')
insert into @t (record,string)values (2,'DEF/123')
insert into @t (record,string)values (3,'GHI/456/XYZ')
declare @mx int
select @mx= len(string)-len(replace(string,'/','')) from @t
select record,t.c.value('.','varchar(max)') as col2 from
(select record,x=cast('<t>'+replace(left(string+'////////////////////',(len(string)+(@mx-(len(string)-len(replace(string,'/','')))))),'/','</t><t>') +'</t>' as xml) from @t)
a cross apply x.nodes('/t') t(c)