专栏首页SQL实现SQL 将多列的数据转到一列

SQL 将多列的数据转到一列

如题。假设我们要把 emp 表中的 ename、job 和 sal 字段的值整合到一列中,每个员工的数据(按照 ename -> job -> sal 的顺序展示)是紧挨在一块,员工之间使用空行隔开。

由于篇幅有限,这里只拿 deptno = 10 的数据来做演示。期望返回的结果如下:

emps       
-----------
CLARK      
MANAGER    
2450       
(NULL)     
KING       
PRESIDENT  
5000       
(NULL)     
MILLER     
CLERK      
1300       
(NULL)     

解决方案

将多列的数据整合到一列展示可以使用 UNION ALL ,只是 UNION ALL 适合数据量比较少且数据固定的场景。一旦增加员工数据或者删除员工数据,UNION ALL 的写法将不再适用。

使用 case when 条件1成立 then ename when 条件2成立 then job when 条件3成立 then sal end 可以将多列的数据放到一列中展示,一行数据过 case when 转换后最多只会出来一个列的值,要使得同一个员工的数据能依次满足 case when 的条件,就需要复制多份数据,有多个条件就要生成多少份数据。判断是否加空行也是 case when 中的条件,因此每个员工的数据都要生成 4 份。

使用笛卡尔积可以"复制"出多份数据,再对这些相同的数据编号(1-4),编号就作为 case when 的判断条件。

完整的SQL 如下:

SELECT
  CASE
    rn
    WHEN 1
    THEN ename
    WHEN 2
    THEN job
    WHEN 3
    THEN CAST(sal AS CHAR(4))
  END emps
FROM
  (SELECT
    e.ename,
    e.job,
    e.sal,
    row_number () over (
      PARTITION BY e.empno
  ORDER BY e.empno
  ) rn
  FROM
    emp e,
    (SELECT
      NULL
    FROM
      emp
    LIMIT 4) four_rows
  WHERE e.deptno = 10) t

不管用什么方式造数据,只要确保派生表 four_rows 的数据只有 4 行就行。

如果使用的数据库不支持窗口函数呢?在 MySQL 里可以使用用户变量,使用用户变量只是模拟了窗口函数的实现,并没有什么新意。

我们可从派生表下手,把本该由窗口函数生成序号的任务交给派生表,这样就不需要窗口函数了。

SELECT
  CASE
    rn
    WHEN 1
    THEN ename
    WHEN 2
    THEN job
    WHEN 3
    THEN CAST(sal AS CHAR(4))
  END emps
FROM
  (SELECT
    e.empno,
    e.ename,
    e.job,
    e.sal,
    four_rows.rn
  FROM
    emp e,
    (SELECT
      1 AS rn
    UNION
    SELECT
      2
    UNION
    SELECT
      3
    UNION
    SELECT
      4) four_rows
  WHERE e.deptno = 10) t
ORDER BY empno,
  rn

封面图由 Mikhail Lebedev 在 Pixabay 上发布

本文分享自微信公众号 - SQL实现(gh_684ee9235a26),作者:zero

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-08-31

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 不用 UNION 操作符实现 UNION 的效果

    当我们要合并两个表或者多个表的结果时,可使用 UNION ALL 或者 UNION 操作符, UNION 和 UNION ALL 的区别在于前者会对结果集去重...

    白日梦想家
  • MySQL 常用日期、时间函数介绍

    MySQL 使用 DATE_FORMAT() 格式化日期,和格式化相关的函数还有 STR_TO_DATE()、TIME_FORMAT() 。

    白日梦想家
  • SQL 打印成绩单

    这是 HackerRank 上的一道中级难度的 SQL 挑战题,实际上考察的是动态排序。

    白日梦想家
  • 牛客网-最小的k个数

    输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4。

    TrueDei
  • 使用Coding企业版自动部署mkdocs文档

    mkdocs自身放在master分支,master分支有修改时调用持续集成,进行构建并把构建后的文件推送回gh-pages分支,再触发持续部署中的静态网站功能,...

    TLingC
  • JS示例36-如何阻止事件冒泡

    专注APP开发
  • C语言 二维数组和指针的一些笔记

    &arr是指整个数组的首地址,而arr是指数组首元素的首地址,虽然所表示的意义不同,但二者之间的值却是相同的。

    小锋学长
  • git中出现的一些问题 原

    晓歌
  • c语言之使用指针将数组进行反转

    绝命生
  • 极简入门,Shiro的认证与授权流程解析

    接下来的几天,我们开讲Shiro,从入门到分析、集成、单点登录整合等几篇。今天我们先来认识一下Shiro吧~

    java思维导图

扫码关注云+社区

领取腾讯云代金券