Với một cột cố định và đã biết, đây là cách thực hiện (tôi đã tự do đặt tên bảng là "điểm"):
Ý tưởng chung:
Để tạo một liên hợp các truy vấn khác nhau và thực thi nó.
Vì bạn cần dữ liệu thực tế làm tiêu đề cột, nên phần đầu tiên của liên hợp sẽ giống như sau:
SELECT 'id', '1', '2', ....
Chỉ riêng truy vấn đó sẽ sao chép kết quả, do đó chúng ta cần cho MySQL biết chúng ta cần có 0 hàng bằng cách thêm LIMIT 0, 0
.
Hàng đầu tiên của liên minh của chúng ta sẽ chứa 'Name'
, cũng như tất cả dữ liệu từ cột "Tên" của bảng. Để có được dòng đó, chúng tôi cần một truy vấn như:
SELECT 'Name',
(SELECT Name FROM grades LIMIT 0, 1),
(SELECT Name FROM grades LIMIT 1, 1),
(SELECT Name FROM grades LIMIT 2, 1),
...
Sử dụng cùng một logic, hàng thứ hai của chúng ta sẽ giống như sau:
SELECT 'Marks',
(SELECT Marks FROM grades LIMIT 0, 1),
(SELECT Marks FROM grades LIMIT 1, 1),
(SELECT Marks FROM grades LIMIT 2, 1),
...
Lấy tiêu đề:
Chúng ta cần tạo một hàng từ MySQL như:
SELECT 'id', '1', '2', ... LIMIT 0, 0;
Để có được dòng đó, chúng tôi sẽ sử dụng CONCAT () và GROUP_CONCAT () chức năng:
SELECT 'id',
(SELECT GROUP_CONCAT(CONCAT(' \'', id, '\'')) FROM grades)
LIMIT 0, 0;
và chúng tôi sẽ lưu dòng đó vào một biến mới:
SET @header = CONCAT('SELECT \'id\', ',
(SELECT GROUP_CONCAT(CONCAT(' \'', id, '\'')) FROM grades),
' LIMIT 0, 0');
Tạo các dòng:
Chúng ta cần tạo hai truy vấn như sau:
SELECT 'Name',
(SELECT Name FROM grades LIMIT 0, 1),
(SELECT Name FROM grades LIMIT 1, 1),
(SELECT Name FROM grades LIMIT 2, 1),
...
Vì chúng tôi không biết trước có bao nhiêu hàng trong bảng gốc của mình, chúng tôi sẽ sử dụng các biến để tạo LIMIT x, 1
khác nhau các câu lệnh. Chúng có thể được sản xuất bằng cách sử dụng những thứ sau:
SET @a = -1;
SELECT @a:[email protected]+1 FROM grades;
Sử dụng đoạn mã này, chúng tôi có thể tạo các truy vấn phụ của mình:
SELECT GROUP_CONCAT(
CONCAT(' (SELECT name FROM grades LIMIT ',
@a:[email protected]+1,
', 1)')
)
FROM grades
Cái mà chúng tôi sẽ đặt vào một tên biến @ line1, cùng với dữ liệu cột đầu tiên (là tên của cột thứ hai):
SET @a = -1;
SET @line1 = CONCAT(
'SELECT \'Name\',',
(
SELECT GROUP_CONCAT(
CONCAT(' (SELECT Name FROM grades LIMIT ',
@a:[email protected]+1,
', 1)')
)
FROM grades
));
Bằng cách tuân theo cùng một logic, dòng thứ hai sẽ là:
SET @a := -1;
SET @line2 = CONCAT(
'SELECT \'Marks\',',
(
SELECT GROUP_CONCAT(
CONCAT(' (SELECT Marks FROM grades LIMIT ',
@a:[email protected]+1,
', 1)')
)
FROM grades
));
Kết hợp tất cả:
Ba biến của chúng tôi hiện chứa:
@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)
Chúng ta chỉ cần tạo một biến cuối cùng bằng cách sử dụng CONCAT()
, chuẩn bị nó dưới dạng một truy vấn mới và thực thi nó:
SET @query = CONCAT('(',
@header,
') UNION (',
@line1,
') UNION (',
@line2,
')'
);
PREPARE my_query FROM @query;
EXECUTE my_query;
Toàn bộ giải pháp:
(để thử nghiệm và tham khảo):
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;
Đầu ra:
+-------+------+-------+ | id | 1 | 2 | +-------+------+-------+ | Name | Ram | Shyam | | Marks | 45 | 87 | +-------+------+-------+ 2 rows in set (0.00 sec)
Chốt lại suy nghĩ:
-
Tôi vẫn không chắc tại sao bạn cần chuyển đổi các hàng thành cột và tôi chắc chắn rằng giải pháp tôi đã trình bày không phải là giải pháp tốt nhất (về mặt hiệu suất).
-
Bạn thậm chí có thể sử dụng giải pháp của tôi như một bước khởi đầu và điều chỉnh nó cho phù hợp với một giải pháp mục đích chung mà tên cột bảng (và số dòng) không được biết, bằng cách sử dụng
information_schema
.COLUMNS
như một nguồn, nhưng tôi đoán điều đó đã đi quá xa. -
Tôi thực sự tin rằng tốt hơn nhiều nếu đặt bảng gốc vào một mảng và sau đó xoay mảng đó, như vậy sẽ nhận được dữ liệu ở định dạng mong muốn.