You don't need a case statement for this
drop table if exists t,t1;
create table t(id varchar(3),a int,b int, c int);
insert into t values
('abc',1,2,3),('def',4,5,6);
select id,a value from t
union all
select id,b from t
union all
select id,c from t
order by id;
+------+-------+
| id | value |
+------+-------+
| abc | 1 |
| abc | 2 |
| abc | 3 |
| def | 4 |
| def | 5 |
| def | 6 |
+------+-------+
6 rows in set (0.00 sec)
НО у вас потенциально есть проблемы - с вашим дизайном вы не можете определить, какая строка пришла из столбца a (столбец b, столбец c и т. Д.).
Чтобы принудительно упорядочить строки в порядке столбцов (слева направо), вам понадобится столбец, в котором будет храниться порядковый номер, чтобы вы могли упорядочить по нему
select id,1 as col,a value from t
union all
select id,2,b from t
union all
select id,3,c from t
order by id,col;
Игнорирование проблем дляТеперь, если вы можете изменить количество столбцов и не хотите перекодировать, тогда используйте подготовленные операторы, возможно, в процедуре можно сделать https://dev.mysql.com/doc/refman/8.0/en/sql-syntax-prepared-statements.html
set @sql =
(
select group_concat(
concat('select id,', column_name, ' as value from t union all ')
)
from
(
select table_name,column_name
from information_schema.columns
where table_name = 't' and table_schema = 'sandbox' and column_name <> 'id'
) s
);
set @sql = (select replace(concat(substring(@sql,1,length(@sql) - 11),';'),',select','select'));
prepare sqlstmt from @sql;
execute sqlstmt;
deallocate prepare sqlstmt;