我在SQL Server 2014中有一个表,下面有2列
ObjectName Whitelist
A Field1,Field2,Field3
B Field1,Field2
使用以下查询,我设法将结果打印如下
SELECT ObjectName,
LTRIM(RTRIM(m.n.value('.[1]','varchar(8000)'))) AS WhiteList
FROM
(
SELECT ObjectName,CAST('<XMLRoot><RowData>' + REPLACE(WhiteList,',','</RowData><RowData>') + '</RowData></XMLRoot>' AS XML) AS x
FROM dbo.testtable
)t
CROSS APPLY x.nodes('/XMLRoot/RowData')m(n)
使用上述查询的实际结果
ObjectName WhiteList
A Field1
A Field2
A Field3
B Field1
B Field2
预期结果
A B
Field1 Field1
Field2 Field2
Field3
答案 0 :(得分:2)
您需要使用Pivot
将行转换为列。
在固定列上更容易实现数据透视。
对于“动态列”,您可以根据结果编写“动态查询”来获得结果。
在Stackoverflow答案中对此进行了很好的解释: Efficiently convert rows to columns in sql server
答案 1 :(得分:1)
CREATE TABLE #TEMP(ObjectName VARCHAR(5), Whitelist VARCHAR(50))
INSERT INTO #TEMP(ObjectName, Whitelist) VALUES ( 'A','Field1,Field2,Field3')
INSERT INTO #TEMP(ObjectName, Whitelist) VALUES ( 'B','Field1,Field2')
SELECT A,B FROM
(
SELECT t1.ObjectName,t1.WhiteList,
Row_Number() over(partition by t1.ObjectName order by t1.Whitelist) RN FROM ---Here We have to use Rownumber()...because they containing the same value
(
SELECT ObjectName,
LTRIM(RTRIM(m.n.value('.[1]','varchar(8000)'))) AS WhiteList
FROM
(
SELECT ObjectName,CAST('<XMLRoot><RowData>' + REPLACE(WhiteList,',','</RowData><RowData>') + '</RowData></XMLRoot>' AS XML) AS x
FROM #TEMP
)t
CROSS APPLY x.nodes('/XMLRoot/RowData')m(n)
)t1 ---Here we will get value in comma seprated......then we can use Pivot
) AS TempTbl
PIVOT
(
MAX(WhiteList) --here you have to use max() function beacuse...your column value doesn't containg any int column...
FOR ObjectName IN (A,B)
) AS PivotTable
输出:-
A B
------------------
Field1 Field1
Field2 Field2
Field3 NULL
答案 2 :(得分:0)
谢谢大家的帮助。通过您在StackOverflow上的评论和其他有用的链接,我可以捕获我在问题中发布的预期结果(第一篇文章)。共享解决方案,以便对有类似要求的人有用。
If OBJECT_ID('tempdb..##tempList') is not null
drop table ##tempList
SELECT ObjectName,
LTRIM(RTRIM(m.n.value('.[1]','varchar(max)'))) AS ColumnName
into ##tempList
FROM
(
SELECT
ObjectName,
CAST('<XMLRoot><RowData>' + REPLACE(whitelist,',','</RowData><RowData>') + '</RowData></XMLRoot>' AS XML) AS x
FROM [dbo].[testtable]
where 1=1
)t
CROSS APPLY x.nodes('/XMLRoot/RowData')m(n)
ORDER BY 1, 2
-- select * from ##tempList -- prints unpivot data
if OBJECT_ID('tempdb..##tempList2') is not null
drop table ##tempList2
select ObjectName, ROW_NUMBER() over(partition by ObjectName order by ColumnName) columnseq, ColumnName
into ##templist2
from ##tempList
DECLARE
@tables NVARCHAR(MAX) = '',
@sql NVARCHAR(MAX) = '';
SELECT
@tables+=QUOTENAME(ObjectName) + ','
FROM
(select distinct ObjectName
from ##templist2
where 1=1
) t
ORDER BY ObjectName;
SET @tables = LEFT(@tables, LEN(@tables) - 1);
SET @sql ='
SELECT ' + @tables + '
FROM
(
select ObjectName, columnseq, ColumnName
from ##templist2
) t
PIVOT(
max(ColumnName)
FOR ObjectName IN ('+ @tables +')
) AS pivot_table;';
EXECUTE sp_executesql @sql;
答案 3 :(得分:-1)
您可以使用string_split()
,但是它不会返回line number
,尽管使用row_number()
有一些解决方法。因此,我更喜欢使用Jeff Moden的DelimitedSplit8K返回一个值。您可以从链接获取代码。 DelimitedSplit8K
解析字符串会返回ItemNumber
和Item
。
declare @sql nvarchar(max) = NULL
select @sql = isnull(@sql, 'SELECT ItemNumber' + char(13))
+ ',max(case when ObjectName = ''' + [ObjectName] + ''' then Item end) AS '
+ quotename(ObjectName) + char(13)
from tbl
select @sql = @sql
+ 'from tbl t' + char(13)
+ 'cross apply DelimitedSplit8K(t.Whitelist, '','')' + char(13)
+ 'group by ItemNumber;'
-- print out the dynamic sql query
print @sql
-- execute the dynamic query
exec sp_executesql @sql