固定された既知の列を使用して、その方法を説明します(テーブルに「グレード」という名前を付けるのは自由です):
一般的なアイデア:
さまざまなクエリの和集合を作成して実行します。
列ヘッダーとして実際のデータが必要なため、結合の最初の部分は次のようになります。
SELECT 'id', '1', '2', ....
そのクエリだけで結果が複製されるため、LIMIT 0, 0
を追加して、MySQLに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),
...
同じロジックを使用すると、2番目の行は次のようになります。
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()<を使用します。 / a> および
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');
行の作成:
次のような2つのクエリを作成する必要があります。
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:[email protected]+1 FROM grades;
このスニペットを使用して、サブクエリを作成できます:
SELECT GROUP_CONCAT(
CONCAT(' (SELECT name FROM grades LIMIT ',
@a:[email protected]+1,
', 1)')
)
FROM grades
これを変数名@line1に、最初の列のデータ(2番目の列の名前)とともに入れます:
SET @a = -1;
SET @line1 = CONCAT(
'SELECT \'Name\',',
(
SELECT GROUP_CONCAT(
CONCAT(' (SELECT Name FROM grades LIMIT ',
@a:[email protected]+1,
', 1)')
)
FROM grades
));
同じロジックに従うと、2行目は次のようになります。
SET @a := -1;
SET @line2 = CONCAT(
'SELECT \'Marks\',',
(
SELECT GROUP_CONCAT(
CONCAT(' (SELECT Marks FROM grades LIMIT ',
@a:[email protected]+1,
', 1)')
)
FROM grades
));
それらすべてを組み合わせる:
これで、3つの変数に次のものが含まれます。
@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:[email protected]+1,
', 1)')
)
FROM grades
));
SET @a := -1;
SET @line2 = CONCAT(
'SELECT \'Marks\',',
(
SELECT GROUP_CONCAT(
CONCAT(' (SELECT Marks FROM grades LIMIT ',
@a:[email protected]+1,
', 1)')
)
FROM grades
));
SET @query = CONCAT('(',
@header,
') UNION (',
@line1,
') UNION (',
@line2,
')'
);
PREPARE my_query FROM @query;
EXECUTE my_query;
出力:
+-------+------+-------+ | id | 1 | 2 | +-------+------+-------+ | Name | Ram | Shyam | | Marks | 45 | 87 | +-------+------+-------+ 2 rows in set (0.00 sec)
最後の考え:
-
行を列に変換する必要がある理由はまだわかりません。また、私が提示したソリューションは(パフォーマンスの点で)最良のソリューションではないと確信しています。
-
information_schema
を使用して、私のソリューションを出発点として使用し、テーブルの列名(および行数)が不明な汎用ソリューションに適合させることもできます。 。COLUMNS
ソースとしてですが、それは行き過ぎだと思います。 -
元のテーブルを配列に入れてからその配列を回転させて、目的の形式でデータを取得する方がはるかに優れていると強く信じています。