最近写了个特别复杂的业务,涉及到一个比较难写的Sql语句,在行转列的基础上需要多表动态联查,也就是说,查询结果的列数是可变的,数量根据联查的表的行数来决定,先贴出语句:
CREATE DEFINER=`root`@`%` PROCEDURE `sp_getpointlist`(projectType INT)
BEGIN
SET @ProjectType = projectType;
SET @SQL = NULL;
SELECT
GROUP_CONCAT( DISTINCT CONCAT( 'Max(IF(s.RuleId = ''', r.Id, ''', s.`Value`, NULL)) AS ''', r.Id, '''' ) ORDER BY r.UpdatedDate ) INTO @SQL
FROM
`new_pb_shieldingpoint` s
RIGHT JOIN `new_pb_rule` r ON r.Id = s.RuleId
WHERE r.ProjectType = projectType
ORDER BY r.UpdatedDate;
SET @SQL = CONCAT( 'Select s.Point,
s.Platform ,
s.ProjectType,
s.UpdatorName,
s.UpdatedDate,', @SQL, ' From new_pb_shieldingpoint s
RIGHT JOIN `new_pb_rule` r ON r.Id = s.RuleId
WHERE s.ProjectType = @ProjectType
GROUP BY s.Point,s.Platform,s.ProjectType
ORDER BY s.Point,s.Platform,s.ProjectType;' );
PREPARE stmt
FROM
@SQL;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END
核心思想是通过GROUP_CONCAT( DISTINCT CONCAT 进行Sql语句的拼接,根据要联查的子表动态生成拼接后的Sql语句,之后再作为静态行转列进行查询,这里有个需要注意的点,如果需要对拼接的动态列进行列的顺序排序,需要写在 GROUP_CONCAT ()内部。
下次要是有人跟我说ORM能解决一切问题、存储过程狗都不写之类的话,我就给他看这个Sql,让他用ORM给我写个这个玩意。