将TableA
与下面提供的数据一起使用,我需要一个SELECT
查询,该结果会在TableB
中返回结果:
表A :
Id Cvs
--------------------------------
1 aaa,eee,ccc,ggg,hhh,bbb
2 ggg,bbb,ccc,ggg,aaa,bbb,bbb
3 ddd,ggg,eee
表B :
Id Value
1 aaa
1 eee
1 ccc
1 ggg
1 hhh
1 bbb
2 ggg
2 bbb
2 ccc
2 ggg
2 aaa
2 bbb
2 bbb
3 ddd
3 ggg
3 eee
由于T-SQL函数或连接查询,请帮助我如何操作。
答案 0 :(得分:0)
请尝试:
DECLARE @table as TABLE(ID int, CVS Nvarchar(50))
insert into @table
select 1, 'aaa,eee,ccc,ggg,hhh,bbb' CVS union all
select 2, 'ggg,bbb,ccc,ggg,aaa,bbb,bbb' CVS union all
select 3, 'ddd,ggg,eee'
;WITH Split_Col
AS
(
SELECT ID, CONVERT(XML,'<table><col>' + ColName + '</col></table>') AS xmlcol
FROM
(
SELECT ID, Split.a.value('.', 'VARCHAR(100)') AS ColName
FROM
(
SELECT ID, CAST ('<M>' + REPLACE(CVS, ',', '</M><M>') + '</M>' AS XML) AS ColName
FROM (select * from @table) TableName
) AS A
CROSS APPLY ColName.nodes ('/M') AS Split(a)
) TableName
)
SELECT
ID, xmlcol.value('/table[1]/col[1]','varchar(100)') AS studentID
FROM Split_Col
order by ID
答案 1 :(得分:0)
试试这个
SELECT A.ID,
Split.a.value('.', 'VARCHAR(100)') AS CVS
FROM
(
SELECT ID,
CAST ('<M>' + REPLACE(CVS, ',', '</M><M>') + '</M>' AS XML) AS CVS
FROM TableA
) AS A CROSS APPLY CVS.nodes ('/M') AS Split(a)
答案 2 :(得分:0)
我会创建一个单独的函数,从CSV列表中返回所有值(包括重复的值):
IF EXISTS (SELECT * FROM sysobjects WHERE id = OBJECT_ID(N'[dbo].[fn_TEST]') AND xtype IN (N'FN', N'IF', N'TF'))
BEGIN
DROP FUNCTION [dbo].[fn_TEST]
END
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [dbo].[fn_TEST]
(
@CSVList NVARCHAR(MAX)
)
RETURNS @ResultSet TABLE
(
RecValue NVARCHAR(MAX)
,RecID BIGINT IDENTITY(1, 1) PRIMARY KEY
)
AS
BEGIN
DECLARE @XML xml = N'<r><![CDATA[' + REPLACE(@CSVList, ',', ']]></r><r><![CDATA[') + ']]></r>'
INSERT INTO @ResultSet (RecValue)
SELECT RTRIM(LTRIM(Tbl.Col.value('.', 'nvarchar(max)')))
FROM @xml.nodes('//r') Tbl(Col)
RETURN
END
GO
然后您可以简单地使用“SELECT”语句和“CROSS APPLY”语句,如下所示:
SET NOCOUNT ON
GO
DECLARE @DataSource AS TABLE
(
ID TINYINT IDENTITY(1,1)
,CSV NVARCHAR(4000)
)
INSERT INTO @DataSource ([CSV])
VALUES ('aaa,eee,ccc,ggg,hhh,bbb')
,('ggg,bbb,ccc,ggg,aaa,bbb,bbb')
,('ddd,ggg,eee')
SELECT ID
,RecValue
FROM @DataSource DS
CROSS APPLY [dbo].[fn_TEST](CSV) FN
SET NOCOUNT OFF
GO
答案 3 :(得分:0)
请尝试其中一项 -
DECLARE @temp TABLE
(
id INT
, string NVARCHAR(200)
)
DECLARE @Separator CHAR(1)
SELECT @Separator = ','
INSERT INTO @temp (id, string)
VALUES
(1, 'aaa,eee,ccc,ggg,hhh,bbb'),
(2, 'ggg,bbb,ccc,ggg,aaa,bbb,bbb'),
(3, 'ddd,ggg,eee')
<强> 1。 XML 强>
SELECT
id = p.value('(./n)[1]', 'INT')
, name = p.value('(./s)[1]', 'NVARCHAR(200)')
FROM (
SELECT field = CAST('<r><s>' + REPLACE(SUBSTRING(',' + t.string + ',', 2, LEN(',' + t.string + ',')), @Separator, '</s><n>' + CAST(t.id AS VARCHAR(10)) + '</n></r><r><s>') + '</s></r>' AS XML)
FROM @temp t
) d
CROSS APPLY field.nodes('/r') t(p)
WHERE t.p.exist('n') = 1
<强> 2。 spt_values 强>
SELECT
t.id
, name =
SUBSTRING(
',' + t.string + ','
, number + 1
, CHARINDEX(@Separator, ',' + t.string + ',', number + 1) - number - 1)
FROM @temp t
CROSS JOIN [master].dbo.spt_values n
WHERE [type] = 'p'
AND number <= LEN(',' + t.string + ',') - 1
AND SUBSTRING(',' + t.string + ',', number, 1) = @Separator
第3。 WHILE 强>
DECLARE @items TABLE
(
id INT
, name NVARCHAR(50)
)
DECLARE
@id INT
, @string NVARCHAR(2000)
, @pos INT
DECLARE cur CURSOR LOCAL FAST_FORWARD READ_ONLY FOR
SELECT id, string
FROM @temp
OPEN cur
FETCH NEXT FROM cur INTO @id, @string
WHILE @@FETCH_STATUS = 0 BEGIN
WHILE LEN(@string) > 0 BEGIN
SELECT @pos = CHARINDEX(@Separator, @string, 1)
IF @pos = 0
SELECT @pos = LEN(@string)
INSERT INTO @items (id, name)
SELECT @id, SUBSTRING(@string, 1, @pos - 1)
SELECT @string = SUBSTRING(@string, @pos + 1, LEN(@string) - @pos)
END
FETCH NEXT FROM cur INTO @id, @string
END
CLOSE cur
DEALLOCATE cur
SELECT
i.id
, i.name
FROM @items i
WHERE name != ''
<强> 4。 CTE 强>
;WITH a AS
(
SELECT
id
, start_pos = 1
, end_pos = CHARINDEX(@Separator, t.string)
, t.string
FROM @temp t
UNION ALL
SELECT
id
, end_pos + 1
, CHARINDEX(@Separator, string, end_pos + 1)
, string
FROM a
WHERE end_pos > 0
)
SELECT
d.id
, d.name
FROM (
SELECT
a.id
, name = SUBSTRING(
string
, start_pos
, ABS(end_pos - start_pos)
)
FROM a
) d
WHERE d.name != ''