SQL如何按照以下格式显示结果

时间:2019-12-11 05:55:23

标签: sql sql-server

我在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 

4 个答案:

答案 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解析字符串会返回ItemNumberItem

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