如何将单个列中的值显示为多个并按另一列显示

时间:2017-06-14 18:47:16

标签: sql sql-server-2012 pivot

我有一个数据库表" table_name1"在SQL Server 2012中使用:

创建
CREATE TABLE table_name1 (
    created_date date,
    complete_hour int,
    col_percent float
);

INSERT INTO table_name1 values
('2017-06-14', 8, 0.3),
('2017-06-14', 9, 1.96),
('2017-06-14', 10, 3.92),
('2017-06-07', 8, 0.17),
('2017-06-07', 9, 2.87),
('2017-06-07', 10, 3.72),
('2017-05-31', 7, 0.14),
('2017-05-31', 8, 0.72),
('2017-05-31', 9, 3.77),
('2017-05-31', 10, 5.8);

我想做的是得到如下结果:

created_date    col1    col2    col3    col4
2017-06-14      BLANK   0.3     1.96    3.92
2017-06-07      BLANK   0.17    2.87    3.72
2017-05-31      0.14    0.72    3.77    5.8

我尝试使用pivot,因为table_name1中的行数会不断变化我认为我必须使用动态sql。所以我尝试使用Efficiently convert rows to columns in sql server帖子中的答案,但无法调整它以解决我的问题。我需要考虑3列而不是2列,并且必须按created_date进行分组。

我可以就如何做到这一点获得一些建议吗?

编辑:我想要遵循的答案的修改版本很少:

DECLARE @cols AS NVARCHAR(MAX),
        @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT ',' + QUOTENAME(col_percent) 
                    from table_name1
                    group by created_date, complete_hour, col_percent
                    order by complete_hour
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = N'SELECT ' + @cols + N' from 
             (
                select created_date, col_percent
                from table_name1                
            ) x
            pivot 
            (
                max(created_date)
                for col_percent in (' + @cols + N')
            ) p '

exec sp_executesql @query;

它的结果如下:

0.14        0.72        0.17        0.3         3.77        2.87        1.96        5.8         3.72        3.92
2017-05-31  2017-05-31  2017-06-07  2017-06-14  2017-05-31  2017-06-07  2017-06-14  2017-05-31  2017-06-07  2017-06-14

我知道我做错了以获得我想要的输出,但当我尝试更改数据透视表中的列名时,我得到或者其他一些更改我得到了"列名无效"或"不正确的值" 0.14"在PIVOT操作员中提供。"

2 个答案:

答案 0 :(得分:1)

您可以执行动态调整以获得所需内容。以下是使用示例中的临时表的示例:

CREATE TABLE #table_name1 (
    created_date date,
    complete_hour int,
    col_percent float
);

INSERT INTO #table_name1 values
('2017-06-14', 8, 0.3),
('2017-06-14', 9, 1.96),
('2017-06-14', 10, 3.92),
('2017-06-07', 8, 0.17),
('2017-06-07', 9, 2.87),
('2017-06-07', 10, 3.72),
('2017-05-31', 7, 0.14),
('2017-05-31', 8, 0.72),
('2017-05-31', 9, 3.77),
('2017-05-31', 10, 5.8);


declare @sql nvarchar(max),
        @pvtColumns nvarchar(max),
        @selectColumns nvarchar(max)

select @pvtColumns = (
                        select ''+PivotColumns+','
                        from (
                            select distinct
                                    '['+convert(Varchar(10), complete_hour)+']' as PivotColumns, complete_hour
                            from #table_name1 
                            ) as b
                        order by complete_hour
                        for xml path('')
                     )

select @pvtColumns = substring(@pvtColumns,1,len(@pvtColumns)-1) 


set @sql = 

'
select 
    p.created_date,
    '+@pvtColumns+'
from        
    (
    select 
        created_date,
        complete_hour,
        col_percent
    from #table_name1 
    )
    as main
    pivot
    (
        max(col_percent)
        for complete_hour in ('+@pvtColumns+')
    ) as p
order by 
    created_date
'

exec sp_Executesql @sql

答案 1 :(得分:1)

如果我们一步一步地采取措施,那么我们首先尝试不使用动态sql。

我相信此查询会产生您要查找的结果:

SELECT created_date, [7] AS col1, [8] AS col2, [9] AS col3, [10] AS col4
FROM 
    (
        select created_date, complete_hour, col_percent
        from table_name1                
    ) x
    pivot 
    (
        max(col_percent)
        for complete_hour in ([7],[8],[9],[10])
    ) p 
    ORDER BY created_date DESC

输出:

created_date    col1    col2    col3    col4
2017-06-14      NULL    0,3     1,96    3,92
2017-06-07      NULL    0,17    2,87    3,72
2017-05-31      0,14    0,72    3,77    5,8

****更新:OP确认结果看起来正确。现在为一些动态的sql ninja-stuff

为了使其更具动态性,以下方法可行:

我们首先声明将保存列和查询的两个变量:

DECLARE @cols AS NVARCHAR(MAX), @query  AS NVARCHAR(MAX)

接下来,我们确定要从表中获取的列。在我们的例子中,这是complete_hour。看到这些最有可能重复几天,我们只想要一次,我们GROUP BY complete_hour

SELECT @cols = STUFF((SELECT ',' + QUOTENAME(complete_hour) 
                    from table_name1
                    group by complete_hour
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

我们现在可以测试变量中的内容:

PRINT @cols 

根据提供的测试数据,目前它将包含

[7],[8],[9],[10]

在现实生活中,这将是每个不同的complete_hour值的值。

建立查询的问题:

set @query = N'SELECT created_date, ' + @cols + N' from 
             (
                select created_date, complete_hour, col_percent
                from table_name1                
            ) x
            pivot 
            (
                max(col_percent)
                for complete_hour in (' + @cols + N')
            ) p 
            ORDER BY created_date DESC
        '

如您所希望的created_date列,需要在SELECT语句中。我们还需要complete_hour的每个值,这是我们存储在@cols中的值。

我们实际上想要抓取所有内容,因此我们选择所有三列,然后为每个complete_hour旋转col_percent。

最后,我们按created_date排序,最新日期首先显示。

然后我们可以执行:

exec sp_executesql @query;