(转)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 ...
随机推荐
- Java学习笔记()ArrayList
1.什么是ArrayList ArrayList就是传说中的动态数组,用MSDN中的说法,就是Array的复杂版本,它提供了如下一些好处: 动态的增加和减少元素 实现了ICollection和ILis ...
- 浅谈BUFF设计
Buff在游戏中无处不在,比如WOW.DOTA.LOL等等,这些精心设计的BUFF,让我们击节赞叹,沉迷其中. 问:BUFF的本质是什么? BUFF 是对一项或多项数据进行瞬间或持续作用的集合.(持续 ...
- Tarojs+redux支付宝小程序开发攻略
技术选型 对于习惯react语法的开发者来讲,RN是实现native的必备工具. 我们甚至可以屏蔽官方稳定而强大的配置层,直接上手开发. 而后,同为表层React语法的Rax.Taro这样的开源多端开 ...
- 【SQL SERVER】触发器(一)
下面是个人对触发器知识的整理,触发器其实很简单,但想要编写发杂的触发器操作还是需要一定的SQL语句编写,触发器主要用于SQL SERVER约束.默认值和规则的完整性检查,还可以实现由主键和外键不能保证 ...
- ref:使用Dezender对zend加密后的php文件进行解密
ref:http://www.cnblogs.com/88223100/ 使用Dezender对zend加密后的php文件进行解密 在开发中需要修改一些php文件,部分是通过zend加密的,记事本 ...
- Angular部署到windows上
1. 确保已经打开了IIS服务. 如果没有打开可参考 http://jingyan.baidu.com/article/eb9f7b6d9e73d1869364e8d8.html 2. 编译angul ...
- prim 算法和 kruskal算法
Prim算法 1.概览 普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树.意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (gra ...
- HDU 5952 [DFS]
题目链接:[http://acm.hdu.edu.cn/showproblem.php?pid=5952] 题意:给出一张无向图,然后判断这张图中一共有多少个不同的大小为S的完全图,并且保证每个点的度 ...
- hdu 4819 二维线段树模板
/* HDU 4819 Mosaic 题意:查询某个矩形内的最大最小值, 修改矩形内某点的值为该矩形(Mi+MA)/2; 二维线段树模板: 区间最值,单点更新. */ #include<bits ...
- 入门cout输出的格式(补位和小数精度)
http://blog.csdn.net/gentle_guan/article/details/52071415 mark一下,妈妈再也不用担心我高精度不会补位了