Ниже MySQL 8.0 подход становится намного более сложным ..
Простое объяснение о сложной части первого запроса
Подзапрос в пределах
SELECT
GROUP_CONCAT(t.col1 ORDER BY col1 ASC) AS cvs
, COUNT(*) AS t_count
FROM
t
создает список значений через запятую.
Затем генератор чисел SQL в сочетании с вложенными функциями SUBSTRING_INDEX()
разделяет значения, разделенные запятыми, на записи.
Который затем объединяется в одну строку с помощью GROUP_CONCAT()
в пользовательскую переменную, в основном я генерирую динамический SQL, который выглядит как '<value>' AS Column<number>[, ...]
, это то, что SELECT @aggregateSQLPart;
показывает вам
Запрос
SET @aggregateSQLPart = NULL;
# set max of GROUP_CONCAT higher as it defaults to 1024 bytes.
SET SESSION group_concat_max_len = @@max_allowed_packet;
SELECT
DISTINCT
GROUP_CONCAT(CONCAT("'",
SUBSTRING_INDEX(
SUBSTRING_INDEX(
t.cvs
, ','
, number_generator.number
)
, ','
, -1
) , "'" , " AS Column", number_generator.number
))
INTO @aggregateSQLPart
FROM (
SELECT
@row := @row + 1 AS number
FROM (
SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
) row1
CROSS JOIN (
SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
) row2
CROSS JOIN (
SELECT @row := 0
) init_user_params
) AS number_generator
CROSS JOIN (
SELECT
GROUP_CONCAT(t.col1 ORDER BY col1 ASC) AS cvs
, COUNT(*) AS t_count
FROM
t
) AS t
WHERE
number BETWEEN 1 AND t_count;
SELECT @aggregateSQLPart;
SET @SQL = CONCAT("
SELECT
"
, @aggregateSQLPart
);
SELECT @SQL;
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Результат
| Column1 | Column2 | Column3 | Column4 | Column5 |
| ------- | ------- | ------- | ------- | ------- |
| A | B | C | D | E |
см. демо
Примечание не сомневайтесь в производительности, которая в среднем выполняется на 5-10 мс на «тестовом» сервере. Также обратите внимание, что я выбираю пользовательские переменные, чтобы вы могли видеть, что происходит в между.