如何在 SQL Server 2008 中将行切换到列,反之亦然

Posted

技术标签:

【中文标题】如何在 SQL Server 2008 中将行切换到列,反之亦然【英文标题】:How to switch rows to columns and vice versa in SQL Server 2008 【发布时间】:2016-09-01 05:44:23 【问题描述】:

我在 SQL Server 2008 中无法将行切换到列,反之亦然,我尝试了对解决方案的任何查询,但没有得到正确的结果。

我有一张如下表:

声明@tmpTable 表 (名称 varchar(20)、date_date、sales_code char(1)、sales smallint、 Earn int) 插入@tmpTable 值(“罗伯特”、“2016/8/1”、“A”、2、30), ('罗伯特', '2016/8/1', 'B', 3, 45), ('罗伯特', '2016/8/2', 'B', 1, 15), ('罗伯特', '2016/8/3', 'B', 2, 30), ('Jhon', '2016/8/1', 'A', 3, 45), ('Jhon', '2016/8/2', 'A', 3, 45), ('Jhon', '2016/8/3', 'B', 2, 30) 从@tmpTable中选择*;

结果:

姓名 date_sales_code 销售额 ------ ---------- ---------- ----- ------ 罗伯特 2016-08-01 A 2 30 罗伯特 2016-08-01 B 3 45 罗伯特 2016-08-02 B 1 15 罗伯特 2016-08-03 B 2 30 约翰 2016-08-01 A 3 45 约翰 2016-08-02 A 3 45 约翰 2016-08-03 B 2 30

然后,我有下一个查询:

选择 * 从 ( 选择名称,'sales_code'作为类别,日期_,sales_code from 选择 * 从 ( 选择名称,日期_ ,STUFF((SELECT ', ' + sales_code [text()] 来自@tmpTable WHERE date_ = t.date_ FOR XML PATH(''), 类型) .value('.','NVARCHAR(MAX)'),1,2,' ') sales_code ,STUFF((SELECT ', ' + convert(varchar(max), sales) [text()] 来自@tmpTable WHERE date_ = t.date_ FOR XML PATH(''), 类型) .value('.','NVARCHAR(MAX)'),1,2,' ') 销售额 ,STUFF((SELECT ', ' + 转换(varchar(max), 获得) [text()] 来自@tmpTable WHERE date_ = t.date_ FOR XML PATH(''), 类型) .value('.','NVARCHAR(MAX)'),1,2,' ') 获得 来自@tmpTable t 按名称分组,日期_ ) 作为一个 ) 作为一个 ) 作为一个 枢轴 ( max(sales_code) FOR date_ IN ([2016/8/1], [2016/8/2], [2016/8/3]) ) 作为光伏 联合所有 选择 * 从 ( 选择名称,“销售额”作为类别,日期_,销售额来自( 选择 * 从 ( 选择名称,日期_ ,STUFF((SELECT ', ' + sales_code [text()] 来自@tmpTable WHERE date_ = t.date_ FOR XML PATH(''), 类型) .value('.','NVARCHAR(MAX)'),1,2,' ') sales_code ,STUFF((SELECT ', ' + convert(varchar(max), sales) [text()] 来自@tmpTable WHERE date_ = t.date_ FOR XML PATH(''), 类型) .value('.','NVARCHAR(MAX)'),1,2,' ') 销售额 ,STUFF((SELECT ', ' + 转换(varchar(max), 获得) [text()] 来自@tmpTable WHERE date_ = t.date_ FOR XML PATH(''), 类型) .value('.','NVARCHAR(MAX)'),1,2,' ') 获得 来自@tmpTable t 按名称分组,日期_ ) 作为一个 ) 作为一个 ) 作为一个 枢轴 ( max(sales) FOR date_ IN ([2016/8/1], [2016/8/2], [2016/8/3]) ) 作为光伏 联合所有 选择 * 从 ( 选择名称,'earned'作为类别,date_,从( 选择 * 从 ( 选择名称,日期_ ,STUFF((SELECT ', ' + sales_code [text()] 来自@tmpTable WHERE date_ = t.date_ FOR XML PATH(''), 类型) .value('.','NVARCHAR(MAX)'),1,2,' ') sales_code ,STUFF((SELECT ', ' + convert(varchar(max), sales) [text()] 来自@tmpTable WHERE date_ = t.date_ FOR XML PATH(''), 类型) .value('.','NVARCHAR(MAX)'),1,2,' ') 销售额 ,STUFF((SELECT ', ' + 转换(varchar(max), 获得) [text()] 来自@tmpTable WHERE date_ = t.date_ FOR XML PATH(''), 类型) .value('.','NVARCHAR(MAX)'),1,2,' ') 获得 来自@tmpTable t 按名称分组,日期_ ) 作为一个 ) 作为一个 ) 作为一个 枢轴 ( max(earned) FOR date_ IN ([2016/8/1], [2016/8/2], [2016/8/3]) ) 作为光伏

它会显示结果:

名称类别 2016/8/1 2016/8/2 2016/8/3 -------- -------- -------- -------- -------- Jhon 销售代码 A、B、A B、A B、B Robert sales_code A、B、A B、A B、B Jhon 销售 2, 3, 3 1, 3 2, 2 罗伯特销售 2, 3, 3 1, 3 2, 2 Jhon 获得 30, 45, 45 15, 45 30, 30 罗伯特赚了 30, 45, 45 15, 45 30, 30

但是,我想得到以下结果:

名称类别 2016/8/1 2016/8/2 2016/8/3 ---- -------- -------- -------- -------- Robert sales_code A, B B B 罗伯特销售 2, 3 1 2 罗伯特赚了 30, 45 15 30 Jhon sales_code A A B 约翰销售 3 3 2 约翰赚了 45 45 30

非常感谢您的帮助。

【问题讨论】:

Stack Overflow 不是免费的代码编写服务,请展示您的代码/努力以及实际问题所在。 @ChrisPickford,我已经更新了我的问题,抱歉我是 Stack Overflow 的新手。 【参考方案1】:

首先您需要对数据进行反透视。为此,所有数据类型都非常匹配,因此您需要将 2 个数字列转换为 varchars。

在 unpivot 之前仍然使用东西来获取每个名称 date_ 的组合值,但使用 distinct 只获取名称 date_ 值一次。

在你取消旋转后,你只需要再次旋转。

SELECT  *
FROM (  SELECT  DISTINCT
                Name, 
                date_,
                sales_code = STUFF((SELECT ', ' + sales_code 
                                    FROM @tmpTable t2 
                                    WHERE t2.Name = t.Name AND t2.date_ = t.date_ 
                                    FOR XML PATH('')), 1, 2, ''),
                sales      = STUFF((SELECT ', ' + CONVERT(VARCHAR, sales) 
                                    FROM @tmpTable t2 
                                    WHERE t2.Name = t.Name AND t2.date_ = t.date_ 
                                    FOR XML PATH('')), 1, 2, ''),
                earned     = STUFF((SELECT ', ' + CONVERT(VARCHAR, earned) 
                                    FROM @tmpTable t2 
                                    WHERE t2.Name = t.Name AND t2.date_ = t.date_ 
                                    FOR XML PATH('')), 1, 2, '') 
        FROM    @tmpTable t) t
UNPIVOT (
    val 
    FOR category IN (sales_code, sales, earned)
) up
PIVOT (
    MAX(val)
    FOR date_ IN ([2016-08-01], [2016-08-02], [2016-08-03])
) p
ORDER BY name DESC, 
        category DESC

【讨论】:

非常感谢你拯救了我的一天。

以上是关于如何在 SQL Server 2008 中将行切换到列,反之亦然的主要内容,如果未能解决你的问题,请参考以下文章

如何在 sql server 2008 中将日期与 GETDATE() 进行比较

如何在 Sql Server 2008 R2 中将列转换为行?

我们如何在 C# 中将访问数据库(.mdb)导入 sql server 2008

在 SQL Server 中将行转换为具有特定条件的列

在 SQL Server 2008 中将查询结果导出到 .csv 文件

在 SQL Server 2008 中将 NVARCHAR 转换为 INT 数据类型