比较经典的SQL行转列+分组集联

这是一个比较经典的行转列。用较少的SQL语句,就可以实现行转列。但是此行转列需要根据业务需要,进行二次开发,根据您的需要进行定制和或重写。

下面就简单聊聊这种形式吧

1.建表脚本

CREATE TABLE [dbo].[Table_1](
 [a] [int] NOT NULL,--目标列名
 [b] [uniqueidentifier] NOT NULL,--目标数据
 [c] [nchar](10) NOT NULL--筛选条件
) ON [PRIMARY]

GO

ALTER TABLE [dbo].[Table_1] ADD  CONSTRAINT [DF_Table_1_b]  DEFAULT (newid()) FOR [b]

2.造数脚本

INSERT [dbo].[Table_1] ([a], [b], [c]) VALUES (78, N‘f01ac2e9-b5bc-4993-926c-9216203db3f1‘, N‘语文‘)
INSERT [dbo].[Table_1] ([a], [b], [c]) VALUES (89, N‘6c2d753b-36a7-468a-bbf7-4bda8beee4df‘, N‘数学‘)
INSERT [dbo].[Table_1] ([a], [b], [c]) VALUES (99, N‘6093ecd4-7b5b-4225-a6d3-dec213f14a6b‘, N‘自习‘)
INSERT [dbo].[Table_1] ([a], [b], [c]) VALUES (12, N‘6961f7f5-a2b0-45b7-8235-305ad22c2295‘, N‘语文‘)
INSERT [dbo].[Table_1] ([a], [b], [c]) VALUES (12, N‘efdf5e97-4fd9-4c05-bbc0-6f18b38bf2d0‘, N‘语文‘)
INSERT [dbo].[Table_1] ([a], [b], [c]) VALUES (44, N‘116d448d-2cd8-4fdf-a7d8-c8f4f53e8e05‘, N‘数学‘)
INSERT [dbo].[Table_1] ([a], [b], [c]) VALUES (55, N‘cf33dbc1-c265-4835-bb17-f684893ad96c‘, N‘自习‘)
INSERT [dbo].[Table_1] ([a], [b], [c]) VALUES (66, N‘f835c374-4fef-4fd9-8a5b-e16f5feb6bda‘, N‘数学‘)
INSERT [dbo].[Table_1] ([a], [b], [c]) VALUES (66, N‘fb0ce23f-a2bc-4d65-82d3-fb137f414fcf‘, N‘自习‘)

3.行转列实现-获取‘语文’类行转列数据

declare @0 nvarchar(4000)--定义动态SQL长度(nvarchar默认最大长度为4000)
set @0=‘select ‘‘Row2Col‘‘ as Demo,‘‘测试分类数据‘‘ as CallBack‘;--拼接头
--set @0=‘select ‘‘‘‘ as A‘;
with other as(select a,b from Table_1 where c=‘语文‘)--结构化获取数据源
select @[email protected]+‘,[‘+CAST([a] as nvarchar(20))+‘]=‘‘‘+CAST([b] as nvarchar(36))+‘‘‘‘ from other --分页动态拼接核心语句
execute sp_executesql @0 --执行动态拼接的SQL

执行结果如下图

图1

从图上可见,多出2列,分别是【Demo】、【CallBack】。

  为什么必须多出2列呢?因为这个执行方式,是基于集合动态拼接,所以SQL语句中是以逗号(,)开头。为了确保SQL的可执行,所以必须追加至少一列数据。

我在此处之所以要追加2列,那是因为除了标识这是动态列结果集以外,还要根据数据拼接的业务进行静态值回调。用以判定当前数据的归属分类。我的CallBack列

可以明确告诉我,这个数据,是“测试分类数据”,我拿到数据后,要对值进行二次筛选,并动态构建缓存业务表,和分类映射表。当然,对你来说,可以忽略不计。

  数据中有重复列?数据中有重复列,我要找12,那么就会造成重名或者目标不明确的现象。那么,我可以非常负责人的说,如果这就是你要的结果,那么你对你的

业务执行,还没有理解好。我们的行转列执行目标除了把数据转过来,还要匹配响应业务。当你执行如上时,请重新考虑下是否有业务分值、数据特例或业务规则分值被

你忽略掉了?

declare @0 nvarchar(4000)
set @0=‘select ‘‘Row2Col‘‘ as Demo,‘‘测试分类数据‘‘ as CallBack‘;
--set @0=‘select ‘‘‘‘ as A‘;
with other as(
select a,b from Table_1
where c=‘自习‘
)
select @[email protected]+‘,[‘+CAST([a] as nvarchar(20))+‘]=‘‘‘+CAST([b] as nvarchar(36))+‘‘‘‘ from other
execute sp_executesql @0

图2

上图是行转列的最终执行目标。即数据明确,列名明确,业务实现明确。

4.约束

通过上面2个列子,可以看出。我们的数据源虽然是3列,但实际组建中必须且仅仅能使用数据源中的2列,显示数据源中的多列是无法做到的;要使用行转列,查询【自习】的结果集是比较理想的。当你出现类似于图1时,就必须停下来自习考虑下,数据源是否可用?是否需要进一步细化数据?业务分析有遗漏?还是数据存在冗余现象?

5.提升

当我希望获取所有数据的行转列时,注释掉other结构块中where试试看?

当我希望做分组集联时,我当前的数据就无法满足了。那么重造数据先,造数脚本如下:

DELETE FROM [dbo].[Table_1]--清空原数据,构建出可以执行分组集联的数据
INSERT [dbo].[Table_1] ([a], [b], [c]) VALUES (78, N‘f01ac2e9-b5bc-4993-926c-9216203db3f1‘, N‘语文‘)
INSERT [dbo].[Table_1] ([a], [b], [c]) VALUES (78, N‘6c2d753b-36a7-468a-bbf7-4bda8beee4df‘, N‘数学‘)
INSERT [dbo].[Table_1] ([a], [b], [c]) VALUES (78, N‘6093ecd4-7b5b-4225-a6d3-dec213f14a6b‘, N‘自习‘)
INSERT [dbo].[Table_1] ([a], [b], [c]) VALUES (12, N‘6961f7f5-a2b0-45b7-8235-305ad22c2295‘, N‘语文‘)
INSERT [dbo].[Table_1] ([a], [b], [c]) VALUES (66, N‘efdf5e97-4fd9-4c05-bbc0-6f18b38bf2d0‘, N‘语文‘)
INSERT [dbo].[Table_1] ([a], [b], [c]) VALUES (12, N‘116d448d-2cd8-4fdf-a7d8-c8f4f53e8e05‘, N‘数学‘)
INSERT [dbo].[Table_1] ([a], [b], [c]) VALUES (12, N‘cf33dbc1-c265-4835-bb17-f684893ad96c‘, N‘自习‘)
INSERT [dbo].[Table_1] ([a], [b], [c]) VALUES (66, N‘f835c374-4fef-4fd9-8a5b-e16f5feb6bda‘, N‘数学‘)
INSERT [dbo].[Table_1] ([a], [b], [c]) VALUES (66, N‘fb0ce23f-a2bc-4d65-82d3-fb137f414fcf‘, N‘自习‘)

图3

上图中,数据是根据分组业务形式,构建的数据,如果你的数据源和我建造的数据类似,那么你的数据源是有做分组集联的可能性的。

提供思路如下:

首先根据游标遍历分类数据集合。

其次使用上面的行转列进行数据转换。

最后把目标数据放入临时表中,集联后返回。

最终执行结果如下:

图4

上图尽是可行性证明,数据具有保密性,所以都做了处理。其可行性毋庸置疑。

稍后再做配套执行脚本,先回家。下班咯~~!

时间: 2024-10-21 23:00:38

比较经典的SQL行转列+分组集联的相关文章

SQL行转列 (及EAV模型获取数据)

参考文章: http://www.williamsang.com/archives/1508.html 情景简介 学校里面记录成绩,每个人的选课不一样,而且以后会添加课程,所以不需要把所有课程当作列.数据库grade里面数据如下图,假定每个人姓名都不一样,作为主键.本文以MySQL为基础,其他数据库会有些许语法不同. 数据库数据: 处理后效果: 下面介绍三种方法: 方法一: 1 2 3 4 5 SELECT DISTINCT  a.name, (SELECT score FROM grade b

SQL 行转列查询汇总

SQL行转列汇总 PIVOT 用于将列值旋转为列名(即行转列),在 SQL Server 2000可以用聚合函数配合CASE语句实现 PIVOT 的一般语法是:PIVOT(聚合函数(列) FOR 列 in (…) )AS P 注意:PIVOT.UNPIVOT是SQL Server 2005 的语法,使用需修改数据库兼容级别(在数据库属性->选项->兼容级别改为 90 ) SQL2008 中可以直接使用 完整语法: table_source PIVOT( 聚合函数(value_column) F

Sql 行转换为列 以及列转换为行的心得

这是 创建数据库的脚本文件 CREATE TABLE [dbo].[stu]( [学号] [nvarchar](255) NOT NULL, [姓名] [nvarchar](255) NULL, [性别] [nvarchar](255) NULL, [专业] [nvarchar](255) NULL, [院系] [nvarchar](255) NULL ) ON [PRIMARY] GO INSERT [dbo].[stu] ([学号], [姓名], [性别], [专业], [院系]) VALU

SQL 行转列

---1.最简单的行转列/* 问题:假设有张学生成绩表(tb)如下:姓名 课程 分数张三 语文 74张三 数学 83张三 物理 93李四 语文 74李四 数学 84李四 物理 94 想变成(得到如下结果): 姓名 语文 数学 物理 李四 74   84   94张三 74   83   93*/--测试用 IF OBJECT_ID('[tb]') IS NOT NULL DROP TABLE [tb] GO create table tb(姓名 varchar(10) , 课程 varchar(

SQL行转列汇总

SQL行转列汇总 PIVOT 用于将列值旋转为列名(即行转列),在 SQL Server 2000可以用聚合函数配合CASE语句实现 PIVOT 的一般语法是:PIVOT(聚合函数(列) FOR 列 in (…) )AS P 注意:PIVOT.UNPIVOT是SQL Server 2005 的语法,使用需修改数据库兼容级别(在数据库属性->选项->兼容级别改为   90 ) SQL2008 中可以直接使用 完整语法: table_source PIVOT( 聚合函数(value_column)

sql 行转列总结

原文:sql 行转列总结 PIVOT UNPIVOT的用法 PIVOT用于将列值旋转为列名(即行转列),在SQL Server 2000可以用聚合函数配合CASE语句实现 PIVOT的一般语法是:PIVOT(聚合函数(列) FOR 列 in (-) )AS P 完整语法: table_source PIVOT( 聚合函数(value_column) FOR pivot_column IN(<column_list>) ) UNPIVOT用于将列明转为列值(即列转行),在SQL Server 2

sql 行转列 PIVOT 列转行 UNPIVOT

原文:sql 行转列 PIVOT 列转行 UNPIVOT 一: 现有表一(t_table1),想转为表二(t_table2)的格式. 表一: 年 公司 收入 2013 公司1 12 2013 公司2 22 2013 公司3 32 2012 公司1 42 2012 公司2 52 2012 公司3 62 表二: 年 公司1 公司2 公司3 2012 42 52 62 2013 12 22 32 可使用sql2005之后提供的PIVOT 具体操作如下: select * from   t_table1

sql 行专列 列转行 普通行列转换

转载:http://www.cnblogs.com/newwind521/archive/2010/11/25/1887203.html sql 行专列 列转行 普通行列转换 /* 标题:普通行列转换(version 2.0) 作者:爱新觉罗.毓华 时间:2008-03-09 地点:广东深圳 说明:普通行列转换(version 1.0)仅针对sql server 2000提供静态和动态写法,version 2.0增加sql server 2005的有关写法.  问题:假设有张学生成绩表(tb)如

SQL行转列经典例子(转载)

行转列问题总结 1.行转列 ---1.最简单的行转列 /* 问题:假设有张学生成绩表(tb)如下: 姓名 课程 分数 张三 语文 74 张三 数学 83 张三 物理 93 李四 语文 74 李四 数学 84 李四 物理 94 想变成(得到如下结果): 姓名 语文 数学 物理 李四 74   84   94 张三 74   83   93 */ --测试用 IF OBJECT_ID('[tb]') IS NOT NULL DROP TABLE [tb] GO create table tb(姓名