SQL进阶教程1-5 外连接的用法:用外连接进行行列转换 :行转列

  本节,我们将通过使用外连接学习格式转换中具有代表性的行列转换和嵌套式侧栏的生成方法。

  

  1.使用外连接进行行列转换 : 行—>列,制作交叉表

  利用下面的Courses表生成右边的课程学习一览记录表。

  

  

一、使用case表达式的解法:

SELECT name, CASE WHEN name IN (SELECT name FROM courses WHERE course LIKE 'SQL入门') THEN 'O'
                  ELSE NULL END AS 'SQL入门',
             CASE WHEN name IN (SELECT name FROM courses WHERE course LIKE 'UNIX基础') THEN 'O'
                  ELSE NULL END AS 'UNIX基础',
             CASE WHEN name IN (SELECT name FROM courses WHERE course LIKE 'Java中级') THEN 'O'
                  ELSE NULL END AS 'Java中级'
FROM courses    
GROUP BY name    

 

二、使用外连接的解法:

SELECT C0.name,
CASE WHEN C1.name IS NOT NULL THEN 'o' ELSE NULL END AS 'SQL入门',
CASE WHEN C2.name IS NOT NULL THEN 'o' ELSE NULL END AS 'UNIX基础',
CASE WHEN C3.name IS NOT NULL THEN 'o' ELSE NULL END AS 'Java中级'
FROM (SELECT DISTINCT name FROM Courses) C0
LEFT JOIN (SELECT name FROM Courses WHERE course = 'SQL入门') C1 ON C0.name = C1.name
LEFT JOIN (SELECT name FROM Courses WHERE course = 'UNIX基础') C2 ON C0.name = C2.name
LEFT JOIN (SELECT name FROM Courses WHERE course = 'Java中级') C3 ON C0.name = C3.name

  首先选定侧边栏,作为主表C0连接其他表;C1~C3是每个课程的学习者的集合,这里以C0为主表,依次对C1~C3进行外连接操作,如果某位员工学习过某个客户课程,则相应的课程列会出现他的姓名,否则为NULL,最后通过CASE表达式将课程列中的员工的姓名转换为o字符。

  上面SQL比较直观,因为大量用到了内嵌视图和连接操作,代码会显得很臃肿。而且随着表头列数的增加,性能也会恶化。

  

  三、一般外连接都可以使用标量子查询替代,所以上面的查询语句可以这样写:

复制代码
SELECT C0.name,
(SELECT ''
FROM Courses C1
WHERE course = 'SQL入门'
AND C1.name = C0.name) AS "SQL入门",
(SELECT ''
FROM Courses C2
WHERE course = 'UNIX 基础'
AND C2.name = C0.name) AS "UNIX基础",
(SELECT ''
FROM Courses C3
WHERE course = 'Java中级'
AND C3.name = C0.name) AS "Java中级"
FROM (SELECT DISTINCT name FROM Courses) C0; -- 这里的C0 是表侧栏
复制代码

使用标量子查询语句来生产3列表头,以“SQL入门”为例,只有当存在name属于C0.name,并且course = 'SQL入门'的行的时候,才会显示符号o,其他情况则不显示。

SELECT ''
FROM Courses C1
WHERE course = 'SQL入门'
AND C1.name = C0.name

  好处:需要增加或者减少课程时,只需要修改SELECT子句即可;

  缺点:性能不太好,在SELECT子句中使用标量子查询,性能开销还是相当大的。

 

四、嵌套CASE表达式

SELECT name , CASE WHEN SUM(CASE WHEN course = 'SQL入门' THEN 1 ELSE 0 END) =1 THEN 'o' ELSE NULL END AS 'SQL入门',
              CASE WHEN SUM(CASE WHEN course = 'UNIX基础' THEN 1 ELSE 0 END) =1 THEN 'o' ELSE NULL END AS 'UNIX基础',
              CASE WHEN SUM(CASE WHEN course = 'Java中级' THEN 1 ELSE 0 END) =1 THEN 'o' ELSE NULL END AS 'Java中级'
FROM courses
GROUP BY name 

  

  不明白:这里的嵌套CASE表达式和前面一中列出的case表达式的性能相比有什么区别呢??

posted @ 2019-07-22 16:53  Garcia11  阅读(275)  评论(0)    收藏  举报
点击右上角即可分享
微信分享提示