(转)SQL查询案例:多行转换为一行
原文:http://www.cnblogs.com/sammon/archive/2012/05/10/2494362.html
测试表与测试数据
CREATE TABLE TestTitle (
name VARCHAR(10),
titleVARCHAR(10)
);
INSERT INTO TestTitle VALUES ('张三', '程序员');
INSERT INTO TestTitle VALUES ('张三', '系统管理员');
INSERT INTO TestTitle VALUES ('张三', '网络管理员');
INSERT INTO TestTitle VALUES ('李四', '项目经理');
INSERT INTO TestTitle VALUES ('李四', '系统分析员');
要求
对于测试数据,要求查询结果为:
张三程序员,系统管理员,网络管理员
李四项目经理,系统分析员
这种结构的结果。
思路
简单查看这个结果,很像对字符型的GROUP BY处理。
数值类型的可以SUM,但是字符类型的无法这么处理。
只好依次MAX(1) + MAX(2) + MAX(3)这种办法来处理。
实现
第一步,设置好分组的编号
SELECT
ROW_NUMBER() OVER(PARTITION BY name ORDER BY title) AS no,
name,
title
FROM
TestTitle
ORDER BY
name,
title
no name title
-------------------- ---------- ----------
1李四 系统分析员
2李四 项目经理
1张三 程序员
2张三 网络管理员
3张三 系统管理员
第二步,根据有编号的子查询,进行分组处理
SELECT
name,
CASE WHEN COUNT(title) = 1 THEN MAX(title)
WHEN COUNT(title) = 2 THEN
MAX( CASE WHEN SubQuery.no = 1 THEN title + ',' ELSE '' END )
+ MAX( CASE WHEN SubQuery.no = 2 THEN titleELSE '' END )
WHEN COUNT(title) = 3 THEN
MAX( CASE WHEN SubQuery.no = 1 THEN title + ',' ELSE '' END )
+ MAX( CASE WHEN SubQuery.no = 2 THEN title + ','ELSE '' END )
+ MAX( CASE WHEN SubQuery.no = 3 THEN titleELSE '' END )
END AS new_title
FROM
(
SELECT
ROW_NUMBER() OVER(PARTITION BY name ORDER BY title) AS no,
name,
title
FROM
TestTitle
) subQuery
GROUP BY
name
执行结果
name new_title
---------- ----------------------------------
李四 系统分析员,项目经理
张三 程序员,网络管理员,系统管理员
对于SQL Server 2005 以上版本使用FOR XML的方式
测试表与测试数据要求
与前面的一样
思路
首先把一个用户的数据,单独的读取出来
然后按照分组进行处理
实现
第一步 把一个用户的数据,单独的读取出来
SELECT
',' + title
FROM
TestTitle
WHERE
name = '张三'
FOR XML PATH('')
第二步Group By每个人
SELECT
name,
STUFF(
(
SELECT
',' + title
FROM
TestTitle subTitle
WHERE
name = TestTitle.name
FOR XML PATH('')
),
1, 1, '') AS allTitle
FROM
TestTitle
GROUP BY
name
执行结果
name allTitle
---------- --------------------------------
李四 项目经理,系统分析员
张三 程序员,系统管理员,网络管理员
对于SQL Server 2005 以上版本使用 CTE 的处理方式 (使用递归方式处理)
WITH t1 AS ( SELECT ROW_NUMBER() OVER(PARTITION BY name ORDER BY title) AS ID, name, title FROM TestTitle ), t2 AS ( SELECT t1.id,
t1.name, CAST(t1.title AS varchar(100)) AS title FROM
t1 WHERE t1.id = 1 UNION ALL SELECT t1.id, t2.name, CAST( t1.title + ',' + t2.title AS varchar(100)) AS title FROM t1, t2 WHERE t1.name = t2.name AND t1.id = (t2.id + 1) ) SELECT name, title FROM t2 WHERE NOT EXISTS ( SELECT 1 FROM t2 t22 WHERE t2.name = t22.name AND t2.id < t22.id );
name title
---------- ----------------------------------------------------------- ------------------------------- 张三 系统管理员,网络管理员,程序员
李四 项目经理,系统分析员
(2 行受影响)
对于MySQL使用 GROUP_CONCAT 函数 的方式进行处理(非常简单)
mysql> SELECT -> name, -> GROUP_CONCAT(title) AS allTitle -> FROM -> TestTitle -> GROUP BY -> name; +------+------------------------------+ | name | allTitle | +------+------------------------------+ | 李四 | 项目经理,系统分析员 | | 张三 | 程序员,系统管理员,网络管理员 | +------+------------------------------+ 2 rows in set (0.00 sec)
对于Oracle使用 WMSYS.WM_CONCAT 函数 的方式进行处理(也非常简单)
SQL> SQL> SELECT 2 name, 3 WMSYS.WM_CONCAT(title) AS allTitle 4 FROM 5 TestTitle 6 GROUP BY 7 name;
NAME ---------- ALLTITLE ------------------------------------------- 李四 项目经理,系统分析员
张三 程序员,系统管理员,网络管理员
对于 DB2 ,也是使用 CTE 递归的方式处理
WITH t1 (id, name, title) AS ( SELECT ROW_NUMBER() OVER(PARTITION BY name ORDER BY title) AS ID, name, title FROM TestTitle ), t2 (id, name, title) AS ( SELECT t1.id, t1.name, CAST(t1.title AS varchar(100)) AS title FROM t1 WHERE t1.id = 1 UNION ALL SELECT t1.id, t2.name, CAST( t1.title || ',' || t2.title AS varchar(100)) AS title FROM t1, t2 WHERE t1.name = t2.name AND t1.id = (t2.id + 1) ) SELECT name, title FROM t2 WHERE NOT EXISTS ( SELECT 1 FROM t2 t22 WHERE t2.name = t22.name AND t2.id < t22.id );
NAME TITLE
---------- --------------------------------------------------------------------- ------------------------------- SQL0347W 递归公共表表达式 "WZQ.T2" 可能包含无限循环。 SQLSTATE=01605
李四 项目经理,系统分析员
张三 网络管理员,系统管理员,程序员
已选择 2 条记录,打印 1 条警告消息。
(转)SQL查询案例:多行转换为一行的更多相关文章
- MS SQL查询所有表行数,获取所有数据库名,表名,字段名
1.获取所有数据库名 --SELECT Name FROM Master..SysDatabases ORDER BY Name -- 2.获取所有表名: --SELECT Name NAMEtemp ...
- sql 多行转换为一行
select 字段1, [val]=( select 字段2 +',' from 表名 as b where b.字段1 = a.字段1 for xml path('')) from 表名 as a ...
- sql查询 ,多行数据合并成一行,并且显示合并后某一列的值拼接结果
select [value] = stuff((select ','+modmb003 from modmb detail where modmb=18 for xml path('')), 1, ...
- SQL 查询重复的行
select * from tbsold where orderid in (select orderid from tbsold group by orderid having count(orde ...
- QL查询案例:取得分组 TOP-N
[转]SQL查询案例:取得分组 TOP-N CREATE TABLE TopnTest ( name VARCHAR(10), --姓名 procDate DATETIME, ...
- Databricks 第11篇:Spark SQL 查询(行转列、列转行、Lateral View、排序)
本文分享在Azure Databricks中如何实现行转列和列转行. 一,行转列 在分组中,把每个分组中的某一列的数据连接在一起: collect_list:把一个分组中的列合成为数组,数据不去重,格 ...
- SQL查询语句去除重复行
1.存在两条完全相同的纪录 这是最简单的一种情况,用关键字distinct就可以去掉 select distinct * from table(表名) where (条件) 2.存在部分字段相同的纪录 ...
- SQL实现多行合并一行 .
ORACLE纯SQL实现多行合并一行[转] 项目中遇到一个需求,需要将多行合并为一行.表结构如下:NAME Null Type ...
- SQL SERVER将多行数据合并成一行(转载)
昨天遇到一个SQL Server的问题:需要写一个储存过程来处理几个表中的数据,最后问题出在我想将一个表的一个列的多行内容拼接成一行 比如表中有两列数据 : ep_classes ep_name A ...
随机推荐
- GLASNICI 解题报告
GLASNICI 解题报告 题目描述 有N个人在一直线上,第i个人的位置为Di,满足Di≤Di+1.最初只有第1个人(在最左边)知道消息. 在任意时刻,每个人可以以每秒1单位的速度向左或向右移动,或者 ...
- ServiceWorker pwa缓存
index.js if ( navigator.serviceWorker ) { console.log("cache index") window.addEventListen ...
- es6的Set()构造函数
关于Set()函数 Set是一个构造器,类似于数组,但是元素没有重复的 1.接收数组或者其他iterable接口的数据 用于初始化数据 let a=new Set([1,32,424,22,12,3, ...
- SCU 4442 Party
二分图的最小点权覆盖. 非常感谢巨巨@islands_的解答,还帮我画了一个图. 题目保证给出的边构成的图是一个二分图. 如果没有第三种类型的$frog$,那么问题就很简单了.即选择哪些点,覆盖住所有 ...
- Markdown 格式如何转换成 Word?
参考资料:https://www.zhihu.com/question/22972843/answer/136008865 markdown语法简洁,写作效率极高,非常适合网络博客.邮件.笔记等非正式 ...
- Docker应用系列(四)| 部署java应用
本示例基于Centos 7,假设目前使用的账号为release,拥有sudo权限. 由于Docker官方镜像下载较慢,可以开启阿里云的Docker镜像下载加速器,可参考此文进行配置. 主机上服务安装步 ...
- iOS 9音频应用播放音频之播放控制暂停停止前进后退的设置
iOS 9音频应用播放音频之播放控制暂停停止前进后退的设置 ios9音频应用播放控制 在“iOS 9音频应用播放音频之ios9音频基本功能”一文可以看到AVAudioPlayer类有很多的属性以及方法 ...
- 创建基于主-从视图的应用程序(Master-Detail Application)
以Master-Detail Application创建的应用程序在iPad和iPhone上都能运行,虽然模板解决了大部分问题,但还是有一些Apple遗留问题需要解决.使用该模板创建项目时,需要将下拉 ...
- [CCC 2018] 平衡树
题面在这里! 根据题目描述就可以直接模拟出一个暴力. 如果把前 n^(1/2) 的树的方案数先一遍 O(n^(3/4)) 暴力预处理出来(其实复杂度并到不了这个级别),然后把n带进来直接暴力算就行了. ...
- 如何在SpringBoot当中上传多个图片或者上传单个图片 工具类
如何在SpringBoot当中上传多个图片[上传多个图片 ] 附赠工具类 1.SpringBoot 上传图片工具类 public class SpringUploadUtil { /*** * 上传图 ...