Я хочу выбрать все строки в моей базе данных, но я хочу, чтобы они были в инвертированной последовательности. Смысл, я хочу использовать первые данные столбца в качестве новых объектов и существующих объектов в качестве первого столбца. Я думаю, вы поняли, что я имею в виду
Вот иллюстрация
id | name | marks ------------------------------- 1 | Ram | 45 -------------------------------- 2 | Shyam | 87
в
id | 1 | 2 | ---------------------------- Name | Ram | Shyam | ---------------------------- Marks | 45 | 87 |
С фиксированными и известными столбцами, вот как это сделать (я взял на себя смелость назвать таблицы «оценки»):
Чтобы создать объединение разных запросов и выполнить его.
Поскольку вам нужны фактические данные в качестве заголовков столбцов, первая часть объединения будет выглядеть так:
SELECT 'id', '1', '2', ....
Только этот запрос будет дублировать результат, поэтому нам нужно сообщить MySQL, что нам нужно иметь 0 строк, добавив LIMIT 0, 0
.
Наша первая строка объединения будет содержать 'Name'
, а также все данные из столбца «Имя» таблицы. Чтобы получить эту строку, нам нужен запрос типа:
SELECT 'Name', (SELECT Name FROM grades LIMIT 0, 1), (SELECT Name FROM grades LIMIT 1, 1), (SELECT Name FROM grades LIMIT 2, 1), ...
Используя ту же логику, наша вторая строка будет выглядеть так:
SELECT 'Marks', (SELECT Marks FROM grades LIMIT 0, 1), (SELECT Marks FROM grades LIMIT 1, 1), (SELECT Marks FROM grades LIMIT 2, 1), ...
Нам нужно создать строку из MySQL, например:
SELECT 'id', '1', '2', ... LIMIT 0, 0;
Чтобы получить эту строку, мы будем использовать функции CONCAT () и GROUP_CONCAT () :
SELECT 'id', (SELECT GROUP_CONCAT(CONCAT(' \'', id, '\'')) FROM grades) LIMIT 0, 0;
и мы собираемся сохранить эту строку в новой переменной:
SET @header = CONCAT('SELECT \'id\', ', (SELECT GROUP_CONCAT(CONCAT(' \'', id, '\'')) FROM grades), ' LIMIT 0, 0');
Нам нужно создать два запроса:
SELECT 'Name', (SELECT Name FROM grades LIMIT 0, 1), (SELECT Name FROM grades LIMIT 1, 1), (SELECT Name FROM grades LIMIT 2, 1), ...
Поскольку мы не знаем заранее, сколько строк есть в нашей исходной таблице, мы будем использовать переменные для генерации различных инструкций LIMIT x, 1
. Они могут быть изготовлены следующим образом:
SET @a = -1; SELECT @a:=@a+1 FROM grades;
Используя этот фрагмент, мы можем создать наши подзапросы:
SELECT GROUP_CONCAT( CONCAT(' (SELECT name FROM grades LIMIT ', @a:=@a+1, ', 1)') ) FROM grades
Который мы будем помещать в переменную names @ line1 вместе с данными первого столбца (это имя второго столбца):
SET @a = -1; SET @line1 = CONCAT( 'SELECT \'Name\',', ( SELECT GROUP_CONCAT( CONCAT(' (SELECT Name FROM grades LIMIT ', @a:=@a+1, ', 1)') ) FROM grades ));
Следуя той же логике, вторая строка будет:
SET @a := -1; SET @line2 = CONCAT( 'SELECT \'Marks\',', ( SELECT GROUP_CONCAT( CONCAT(' (SELECT Marks FROM grades LIMIT ', @a:=@a+1, ', 1)') ) FROM grades ));
Теперь наши три переменные содержат:
@header: SELECT 'id', '1', '2' LIMIT 0, 0 @line1: SELECT 'Name', (SELECT Name FROM grades LIMIT 0, 1), (SELECT name FROM grades LIMIT 1, 1) @line2: SELECT 'Marks', (SELECT Marks FROM grades LIMIT 0, 1), (SELECT marks FROM grades LIMIT 1, 1)
Нам просто нужно создать конечную переменную с помощью CONCAT()
, подготовить ее как новый запрос и выполнить ее:
SET @query = CONCAT('(', @header, ') UNION (', @line1, ') UNION (', @line2, ')' ); PREPARE my_query FROM @query; EXECUTE my_query;
(для тестирования и ссылки):
SET @header = CONCAT('SELECT \'id\', ', (SELECT GROUP_CONCAT(CONCAT(' \'', id, '\'')) FROM grades), ' LIMIT 0, 0'); SET @a = -1; SET @line1 = CONCAT( 'SELECT \'Name\',', ( SELECT GROUP_CONCAT( CONCAT(' (SELECT Name FROM grades LIMIT ', @a:=@a+1, ', 1)') ) FROM grades )); SET @a := -1; SET @line2 = CONCAT( 'SELECT \'Marks\',', ( SELECT GROUP_CONCAT( CONCAT(' (SELECT Marks FROM grades LIMIT ', @a:=@a+1, ', 1)') ) FROM grades )); SET @query = CONCAT('(', @header, ') UNION (', @line1, ') UNION (', @line2, ')' ); PREPARE my_query FROM @query; EXECUTE my_query;
Вывод:
+ ------- + ------ + ------- + | id | 1 | 2 | + ------- + ------ + ------- + | Имя | Рам | Шейм | | Знаки | 45 | 87 | + ------- + ------ + ------- + 2 ряда в наборе (0,00 сек)
Я все еще не уверен, почему вам нужно преобразовать строки в столбцы, и я уверен, что предлагаемое мной решение не самое лучшее (с точки зрения производительности).
Вы можете даже использовать мое решение в качестве запуска и адаптировать его к решению общего назначения, где имена столбцов таблицы (и количество строк) неизвестны, используя information_schema
. COLUMNS
как источник, но я думаю, что это слишком далеко.
Я твердо верю, что гораздо лучше поместить исходную таблицу в массив и затем повернуть этот массив, тем самым получив данные в нужном формате.
Похоже на то, что вы ищете, это кросс-таблица (или транспонирование) на ваших данных.
Вот отличная статья, описывающая, как это сделать: http://onlamp.com/pub/a/onlamp/2003/12/04/crosstabs.html – это немного устаревший, хотя и не уверен, что в настоящее время существует более эффективный способ чтобы сделать это. Он работает достаточно хорошо для меня.
В командной строке вы можете завершить свой запрос с помощью \ G для достижения этого, например
select * from `students`\G;