我有下表及详细信息:
示例:
CREATE TABLE Table1
(`PK` int, `Name` varchar(3), `Subject` varchar(9), `Grade` varchar(1));
INSERT INTO Table1
(`PK`, `Name`, `Subject`, `Grade`)
VALUES
(1, 'Bob', 'Math', 'A'),
(2, 'Bob', 'History', 'B'),
(3, 'Bob', 'Language', 'C'),
(4, 'Bob', 'Biology', 'D'),
(5, 'Sue', 'History', 'C'),
(6, 'Sue', 'Math', 'A'),
(7, 'Sue', 'Music', 'A'),
(8, 'Sue', 'Geography', 'C');
现在我想编写一个存储过程,我希望通过该过程来转动表。
DELIMITER $$
create PROCEDURE sptest1(IN nm varchar(50),IN sub varchar(50))
begin
SET @sql = NULL;
SELECT GROUP_CONCAT(DISTINCT
CONCAT('MAX(CASE WHEN ', nm ,' = ''', nm,
''' THEN grade END) `', nm, '`'))
INTO @sql
FROM table1;
SET @sql = CONCAT('SELECT ', sub ,',', @sql, '
FROM table1
GROUP BY ', sub ,'');
select @sql;
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END$$
DELIMITER ;
调用功能:
call sptest1('name','subject')
但结果错了:
subject name
----------------
Biology null
Geography null
History null
Language null
Math null
Music null
预期结果:
subject Bob Sue
-------------------------
Biology D null
Geography null C
History B C
Language C null
Math A A
Music null A
答案 0 :(得分:1)
您可以将动态sql查询重写为
SET @sql = NULL;
SELECT GROUP_CONCAT( DISTINCT
CONCAT('MAX(CASE WHEN `Name` = ''',
`Name`,
''' THEN grade END) ',
`Name`)
)
INTO @sql
FROM table1;
SET @sql = CONCAT('SELECT `Subject`, ', @sql, ' FROM table1 GROUP BY `Subject`');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Demo
在您的存储过程中,如果您将其作为参数传递,则必须为动态sql硬编码您的名称列,然后您可以使用大小写来检查列,例如
MAX(CASE WHEN ', nm ,' = ''', nm, ..
上述部分程序将评估为MAX(CASE WHEN name = 'name' ..
,因为变量nm
包含“名称”,它不会将其识别为列
DROP PROCEDURE `sptest1`;
DELIMITER $$
CREATE
PROCEDURE `sib`.`sptest1`(IN nm VARCHAR(50),IN sub VARCHAR(50))
BEGIN
SET @sql = NULL;
SELECT GROUP_CONCAT( DISTINCT
CONCAT('MAX(CASE WHEN ',nm,' = ''',CASE WHEN nm = 'name' THEN `Name` END,''' THEN grade END) ',CASE WHEN nm = 'name' THEN `Name` END)
)
INTO @sql
FROM table1;
SET @sql = CONCAT('SELECT ', sub ,',', @sql, ' FROM table1 GROUP BY ', sub ,'');
/*select @sql; */
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END$$
DELIMITER ;
Demo