(转)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 条警告消息。

时间: 2024-10-06 09:13:10

(转)SQL查询案例:多行转换为一行的相关文章

MS SQL查询所有表行数,获取所有数据库名,表名,字段名

1.获取所有数据库名 --SELECT Name FROM Master..SysDatabases ORDER BY Name -- 2.获取所有表名: --SELECT Name NAMEtemp,* FROM TEST..SysObjects Where XType='U' ORDER BY Name --表名  ----XType='U':表示所有用户表; ----XType='S':表示所有系统表; 3.获取所有字段名: SELECT Name FROM SysColumns WHER

sql查询 ,多行数据合并成一行,并且显示合并后某一列的值拼接结果

select  [value] = stuff((select ','+modmb003  from modmb detail where modmb=18 for xml path('')), 1, 1, '') 其中stuff的作用是:删除指定长度的字符,并在指定的起点处插入另一组字符 语法:STUFF ( character_expression , start , length ,character_expression ) 列:SELECT STUFF('abcdef', 2, 3,

SQL 查询数据后行数据合并为列

SQL 将查询后得到的多行数据中的某一列转为一列,如原查找后的结果为: USER_NAME 张三 李四 王五 现要将其合并为: CUSTOMER 张三,李四,王五 SQL语句如下:select STUFF((select ','+USER_NAME from tbale where USER_NAME = '' for xml path('')), 1, 1, '') CUSTOMER 其中,stuff为sql封装好的一个方法函数,用于删除指定长度的字符并在指定的起始点插入另一组字符. 语法:S

sql查询出来的列转换为逗号隔开的字符串

select top 1000 fid,replace(stuff((select distinct ','+substring(f_paez_spmc1,1,charindex(' ',f_paez_spmc1)) from PAEZ_t_xsxxxx where f_paez_spdm like '01%'and c.fid=fid for xml path('')),1,1,''),' ','') as CookNames from PAEZ_t_xsxxxx c group by c.f

sql的基础语句-单行函数,dual,数字函数,日期函数,表连接,集合运算,分组报表,单行子查询,多行子查询

3. 单行函数 3.1 转换函数 select ascii('A'),chr(65) from dual; select to_char(1243123),1231451 from dual;靠左边的就是字符串,靠右边的就是数字 select to_char(123512a121) from dual;   --错误的写法,没有引号表示数字,但是数字里面包含了字母,不合法的输入值 select to_number('123141211') from dual; select to_number(

SQL查询语句去除重复行

1.存在两条完全相同的纪录 这是最简单的一种情况,用关键字distinct就可以去掉 select distinct * from table(表名) where (条件) 2.存在部分字段相同的纪录(有主键id即唯一键) 如果是这种情况的话用distinct是过滤不了的,这就要用到主键id的唯一性特点及group by分组 select * from table where id in (select min(id) from table group by [去除重复的字段名列表,....])

执行一次SQL查询,修改UPDATE多行记录

通常情况下,我们会使用以下SQL语句来更新字段值: UPDATE mytable SET myfield='value' WHERE other_field='other_value';UPDATE mytable SET myfield='value' WHERE other_field='other_value'; 但是,如果你想更新多行数据,并且每行记录的各字段值都是各不一样,你会怎么办呢?举个例子,我的博客有三个分类目录(免费资源.教程指南.橱窗展示),这些分类目录的信息存储在数据库表c

sql里将重复行数据合并为一行,数据用逗号分隔

DECLARE @T1 table ( UserID int , UserName nvarchar(50), CityName nvarchar(50) ); insert into @T1 (UserID,UserName,CityName) values (1,'a','上海') insert into @T1 (UserID,UserName,CityName) values (2,'b','北京') insert into @T1 (UserID,UserName,CityName)

sql语句查询后几行数据并倒着排列

$conn = mysql_connect("数据库地址","用户名","密码"); if(!$conn) { die("mysql conn failed"); } else{ mysql_query("SET NAMES 'utf8'"); mysql_select_db("数据表",$conn); if(!$conn) { die("database selected f