`
lixiamani
  • 浏览: 38839 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

SQL查询案例:多行转换为一行

 
阅读更多
使用通常的方式
测试表与测试数据
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 条警告消息。


http://hi.baidu.com/wangzhiqing999/blog/item/a57d1a86009e439ff703a67a.html
分享到:
评论

相关推荐

    VB.NET源码 -一行多列转一列多行数据.txt

    标题中的"一行多列转一列多行数据"就是一个典型的行列转换问题,它涉及到数据结构的转换和遍历。在这个案例中,提供的资源可能是一个包含VB.NET源代码的文本文件,用于解决此类问题。 首先,我们需要理解这个问题的...

    sql动态行转列 存储过程

    在SQL数据库操作中,"行转列"是一种常见的数据转换需求,它将表格中的多行数据转换为单列显示,通常用于数据汇总和分析。在本案例中,我们主要探讨如何使用SQL语句,尤其是存储过程,来实现动态的行转列功能。这在...

    sql行转列解决方案.

    标题与描述均提到“SQL行转列解决方案”,这主要指的是在SQL中将数据表中的行数据转换为列数据的一种操作技巧,通常应用于需要对多行数据进行汇总展示或数据分析的场景。这种转换对于数据报告、统计分析等业务需求至...

    SQL.21日自学通(中文版)

    - **单行子查询**:结果集中只有一行数据的子查询。 - **多行子查询**:结果集中有多行数据的子查询。 - **相关子查询**:子查询的结果依赖于外层查询中的某个值。 - **EXISTS关键字**:用于检查子查询是否返回行。 ...

    21天自学sql

    - 过滤行:`SELECT * FROM table WHERE condition;` - 排序列:`SELECT * FROM table ORDER BY column ASC/DESC;` - **示例**:执行第一个查询:`SELECT * FROM employees;` **五、表达式、条件语句与运算** - *...

    SQL自学通.pdf

    - **SQL简介**:SQL(Structured Query Language,结构化查询语言)是一种用于管理关系型数据库的标准语言。 - **SQL简史**:SQL由IBM的Raymond Boyce和Donald Chamberlin在1970年代初提出,最初名为SEQUEL...

    SQL行转列范例教程

    本文档通过一个具体的案例来详细阐述如何实现这一转变,并提供了一个实际的SQL脚本来完成这一任务。 #### 二、关键概念解析 ##### 1. 分组字段 分组字段是一组字段(可以是一个或多个),用于对数据进行分组。例如...

    程序员的SQL金典.rar

     11.8.1 将结果集转置为一行  11.8.2 把结果集转置为多行  11.9 递归查询  11.9.1 Oracle中的CONNECT BY子句  11.9.2 Oracle中的SYS_CONNECT_BY_PATH()函数  11.9.3 My SQL Server和DB2中递归查询 附录A 常用...

    21天精通SQL操作

    根据提供的文档信息,可以看出这是一本关于SQL学习的书籍,主要涵盖了从基础知识到高级操作的各种内容。接下来将根据这些信息生成一系列与SQL相关的知识点。 ### 1. SQL基础语法及使用方式 #### 1.1 SQL简介 - **...

    Sql Server数据把列根据指定内容拆分数据的方法实例

    在这个例子中,`nodes('/root/v')`将每个`&lt;v&gt;`元素转化为一行记录。 然后,我们利用`outer apply`进行关联。`outer apply`类似于`LEFT JOIN`,但它的关联条件不是通过`ON`子句来设定,而是通过查询表达式直接关联。...

    SQL21自学通.pdf

    《SQL21自学通》是一本详尽的指南,旨在帮助初学者到进阶学习者掌握SQL语言的基础知识和高级...通过系统的学习,读者将能够熟练掌握SQL语言,有效地管理、查询和分析数据,为数据分析、软件开发等领域打下坚实的基础。

    mysql常见函数介绍与案例解析.zip

    - `GROUP_CONCAT()`:将多行合并为一个字符串,以逗号分隔。 5. **条件判断函数** - `IF()`:根据条件返回两个可能的值。 - `IFNULL()`:如果表达式为NULL,则返回第二个参数。 - `COALESCE()`:返回第一个非...

    第22讲 SQL语言高级03--函数.PPT

    单行函数如其名,针对每一行返回一个单独的结果值,而多行函数则可能返回多行结果。 3-5中详细解释了单行函数的特性,包括它们如何处理数据项、接受参数、返回单个值,以及如何对每行数据进行操作。它们可以嵌套...

    SQL参考手册

    本章提供了多个实际应用场景下的SQL使用案例,如数据转换、数据查询和统计分析,帮助用户更好地理解如何在实际工作中运用SQL。 #### 第四章 系统工具参考 介绍了几种用于管理和操作HGSQL的工具,如`SQLCMD`命令行...

    SQL 21日自学通.pdf

    - **相关子查询**:相关子查询是依赖于外层查询的某些值的子查询,通常用于处理多行或多列的情况。 - **EXISTS、ANY、ALL的使用**:这些关键字用于简化子查询的书写,提高查询效率。 #### 第一周回顾 - **预览**:...

    Oracle行列转换_总结

    行转列是指将多行数据转换为一行多列的形式。这种转换在汇总或分组数据时特别有用。 **1. AGGREGATE FUNCTION 方法** - **适用版本**: Oracle 8i 及以上 - **操作原理**: 使用 `MAX` 函数(或其他聚合函数)结合...

    hive影评案例.zip

    4. **MovieTypeUDTF.java** - 这是一个Java源代码文件,名字中的"UDTF"通常代表User Defined Table-Valued Function,这是Hive中的一种函数类型,用于扩展Hive的功能,将单行输入转换为多行输出。这个特定的函数可能...

    免费电子书《MySQL实战教程》

    - 逻辑设计:将ER图转换为关系模式,确定表结构、键值等。 #### 二、数据库基本操作 - **数据定义语言(DDL)**: - 创建表:使用CREATE TABLE语句定义表结构。 - 修改表:使用ALTER TABLE来添加、删除列或更改列...

    玩转-SQL2005数据库行列转换

    在本案例中,我们将深入探讨如何在SQL Server 2005中实现这两种转换。 首先,我们来看行转列的实现。在SQL Server 2005中,通常可以使用PIVOT操作或者通过动态SQL配合CASE WHEN语句来完成。例如,给定一个名为...

    sqluldr-oracle.rar

    4. 多行记录:对于数据文件中跨多行的记录,SQL*Loader可以通过设置ROW FORMAT DELIMITED选项处理。 5. 分区加载:对于分区表,可以指定直接加载到特定分区,提高效率。 四、数据流转与优化 在数据流转过程中,SQL...

Global site tag (gtag.js) - Google Analytics