Моя таблица исходит из вывода хранимой процедуры. Это выглядит как :
col1
A
B
C
D
Он может иметь меньше или равно 5 строк.
Я хочу, чтобы это выглядело так
Column1 Column2 Column3 Column4 column5
A B C D NULL
Есть ли способ добиться этого в MYSQL?
Проблема в том, что я не знаю, как я могу использовать оператор IF здесь, так как есть только один столбец, и он меняется после каждого запроса. поэтому мне не с чем сравнивать оператор IF
Возможный дубликат Транспонировать запрос MySQL - нужны строки в столбцы
Без столбца, который указывает порядок, вы не можете надежно преобразовать эти записи в соответствующие столбцы. Поскольку результаты/таблицы SQL определены как беспорядочный по стандартам, если только ORDER BY col1
не подходит для использования вне курса.
@RaymondNijland Честно говоря, меня не волнует порядок. Все, что я хочу, чтобы они были в один ряд. один из способов, который я делаю, похож на этот SET var1 = (SELECT listingid FROM final_table LIMIT 1); SET var2 = (SELECT listingid FROM final_table LIMIT 1,1); но я чувствую, что это будет медленнее, как если бы у меня было, скажем, 10 строк.
ладно подумаю..
В MySQL 8+ есть довольно простой способ сделать это, используя ROW_NUMBER
вместе со сводным запросом:
WITH cte AS (
SELECT col1, ROW_NUMBER() OVER (ORDER BY col1) rn
FROM yourTable
)
SELECT
MAX(CASE WHEN rn = 1 THEN col1 END) AS Column1,
MAX(CASE WHEN rn = 2 THEN col1 END) AS Column2,
MAX(CASE WHEN rn = 3 THEN col1 END) AS Column3,
MAX(CASE WHEN rn = 4 THEN col1 END) AS Column4,
MAX(CASE WHEN rn = 5 THEN col1 END) AS Column5
FROM cte;
к сожалению, все же пробило на 5.1 :(
Ниже 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 мс на «тестовом» сервере. Также обратите внимание, что я выбираю пользовательские переменные, чтобы вы могли видеть, что происходит между ними.
О... М... Г +1. На самом деле, я предпочитаю просто SELECT 'A' AS Column1, 'B' AS Column2 etc.
мне @TimBiegeleisen, но это был единственный способ сделать его на 100% динамичным.
Дублировано: stackoverflow.com/questions/13581482/…