SQL 经典问题:列转行

情景分析:

如上文 经典SQL问题: 行转列所示情节,反过来。
数据库数据为:
grade_result

处理后效果(id可以不要):
grade_table

方法一:

SELECT*FROM(
SELECTname,'语文'ascourse, 语文asscoreFROMgrade2
unionall
SELECTname,'数学'ascourse, 数学asscoreFROMgrade2
unionall
SELECTname,'英语'ascourse, 英语asscoreFROMgrade2
) tmpTable

这里别名不要忘了写:tmpTable。

方法二:

涉及知识点:可以通过查询表:INFORMATION_SCHEMA.COLUMNS 获取数据库表中的各个字段。可以通过执行如下语句进行观察

SELECT*FROMINFORMATION_SCHEMA.COLUMNS;

我们需要获取除name字段以外的所有字段SQL如下:

SELECTCOLUMN_NAMEFROMINFORMATION_SCHEMA.COLUMNSWHERETABLE_SCHEMA ='test'ANDTABLE_NAME='grade2'ANDCOLUMN_NAME <>'name';

这里的数据库名称为test,根据实际情况精心替换。

DELIMITER &&
CREATEPROCEDUREsp_trans()
BEGIN
#课程名称
DECLAREcourse_nVARCHAR(20);
#所有课程数量
DECLAREcountINT;
#计数器
DECLAREiINTDEFAULT0;
#拼接SQL字符串
SET@s ='SELECT * FROM (';
SETcount= (SELECTCOUNT(*)FROMINFORMATION_SCHEMA.COLUMNSWHERETABLE_SCHEMA ='jd'ANDTABLE_NAME='grade2'ANDCOLUMN_NAME <>'name');
WHILE i <countDO
SETcourse_n = (SELECTCOLUMN_NAMEFROMINFORMATION_SCHEMA.COLUMNSWHERETABLE_SCHEMA ='jd'ANDTABLE_NAME='grade2'ANDCOLUMN_NAME <>'name'LIMIT i,1);
SET@s = CONCAT(@s ,' SELECT name, "');
SET@s = CONCAT(@s , course_n);
SET@s = CONCAT(@s,'", ');
SET@s = CONCAT(@s, course_n);
SET@s = CONCAT(@s,' as score FROM grade2 ');
IF i <>count-1THEN
SET@s = CONCAT(@s,'union all');
ENDIF;
SETi = i+1;
ENDWHILE;
SET@s = CONCAT(@s,' ) tepTable');
#用于调试
#SELECT@s;
PREPAREstmtFROM@s;
EXECUTEstmt;
END

方法分析:

方法一使用了手动列举列,产生数据后,union数据。
方法二使用存储过程,从MySQL schem获取表最新表字段,拼接SQL。实际上是方法一的动态扩展。

Note:

可以从前文:经典SQL问题: 行转列的检索结果直接创建新表,省去了自己建表填表的麻烦:

CREATETABLEgrade2
SELECTname,
SUM(CASEcourseWHEN'语文'THENscoreEND)AS'语文',
SUM(CASEcourseWHEN'数学'THENscoreEND)AS'数学',
SUM(CASEcourseWHEN'英语'THENscoreEND)AS'英语'
FROMgradeGROUPBYname

你可能感兴趣的:(SQL 经典问题:列转行)