用外连接进行行列转换(行→列)
courses表:
CREATE TABLE Courses (name VARCHAR(32), course VARCHAR(32), PRIMARY KEY(name, course)); INSERT INTO Courses VALUES('赤井', 'SQL入门'); INSERT INTO Courses VALUES('赤井', 'UNIX基础'); INSERT INTO Courses VALUES('铃木', 'SQL入门'); INSERT INTO Courses VALUES('工藤', 'SQL入门'); INSERT INTO Courses VALUES('工藤', 'Java中级'); INSERT INTO Courses VALUES('吉田', 'UNIX基础'); INSERT INTO Courses VALUES('渡边', 'SQL入门');
需转换成下表:
方法及分析如下:
/* 水平展开求交叉表(1):使用外连接 代码臃肿,不易于扩展,表头列数增加性能会恶化 */ SELECT C0.name, CASE WHEN C1.name IS NOT NULL THEN '○' ELSE NULL END AS "SQL入门", CASE WHEN C2.name IS NOT NULL THEN '○' ELSE NULL END AS "UNIX基础", CASE WHEN C3.name IS NOT NULL THEN '○' ELSE NULL END AS "Java中级" FROM (SELECT DISTINCT name FROM Courses) C0 LEFT OUTER JOIN (SELECT name FROM Courses WHERE course = 'SQL入门' ) C1 ON C0.name = C1.name LEFT OUTER JOIN (SELECT name FROM Courses WHERE course = 'UNIX基础' ) C2 ON C0.name = C2.name LEFT OUTER JOIN (SELECT name FROM Courses WHERE course = 'Java中级' ) C3 ON C0.name = C3.name; /* 水平展开(2):使用标量子查询 易于扩展,增加PHP列时,只需要增加: (SELECT '○' FROM Courses C4 WHERE course = 'PHP入门' AND C4.name = C0.name) AS "PHP入门" 缺点是在select语句中使用标量子查询(或关联子查询)时,开销相当大 */ 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; /* 水平展开(3):嵌套使用CASE表达式 聚合函数:SUM/MAX/MIN/AVG/COUNT 聚合函数的执行结果也是标量值,因此可以像常量和普通列一样使用 这里将聚合函数的返回值作为CASE表达式的判断条件 */ SELECT name, CASE WHEN SUM(CASE WHEN course = 'SQL入门' THEN 1 ELSE NULL END) >= 1 THEN '○' ELSE NULL END AS "SQL入门", CASE WHEN SUM(CASE WHEN course = 'UNIX基础' THEN 1 ELSE NULL END) >= 1 THEN '○' ELSE NULL END AS "UNIX基础", CASE WHEN SUM(CASE WHEN course = 'Java中级' THEN 1 ELSE NULL END) >= 1 THEN '○' ELSE NULL END AS "Java中级" FROM Courses GROUP BY name;
用外连接进行行列转换(列→行)
Personnel表:
CREATE TABLE Personnel (employee varchar(32), child_1 varchar(32), child_2 varchar(32), child_3 varchar(32), PRIMARY KEY(employee)); INSERT INTO Personnel VALUES('赤井', '一郎', '二郎', '三郎'); INSERT INTO Personnel VALUES('工藤', '春子', '夏子', NULL); INSERT INTO Personnel VALUES('铃木', '夏子', NULL, NULL); INSERT INTO Personnel VALUES('吉田', NULL, NULL, NULL);
需转换成下表:
方法及分析如下:/*先创建一个孩子的视图/* 孩子主表
CREATE VIEW Children(child) AS SELECT child_1 FROM Personnel UNION SELECT child_2 FROM Personnel UNION SELECT child_3 FROM Personnel; 获取员工子女列表的SQL语句(没有孩子的员工也输出) */ SELECT EMP.employee, CHILDREN.child FROM Personnel EMP LEFT OUTER JOIN Children ON CHILDREN.child IN (EMP.child_1, EMP.child_2, EMP.child_3);
版权声明:本文章部分内容转载自《SQL进阶教程》作者:MICK ,出版社:人民邮电出版社,
文章仅供学习交流使用,转载请附上原文出处链接和本声明。