Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Wählen Sie MYSQL-Zeilen, aber Zeilen in Spalten und Spalten in Zeilen aus

Mit festen und bekannten Spalten geht das so (ich habe mir erlaubt, die Tabelle "Noten" zu nennen):

Allgemeine Idee:

Um eine Vereinigung verschiedener Abfragen zu erstellen und auszuführen.

Da Sie tatsächliche Daten als Spaltenüberschriften benötigen, sieht der erste Teil der Vereinigung folgendermaßen aus:

SELECT 'id', '1', '2', ....

Diese Abfrage allein wird das Ergebnis duplizieren, daher müssen wir MySQL mitteilen, dass wir 0 Zeilen haben müssen, indem wir LIMIT 0, 0 hinzufügen .

Unsere erste Zeile der Vereinigung enthält 'Name' , sowie alle Daten aus der Spalte "Name" der Tabelle. Um diese Zeile zu erhalten, benötigen wir eine Abfrage wie:

SELECT 'Name',
    (SELECT Name FROM grades LIMIT 0, 1),
    (SELECT Name FROM grades LIMIT 1, 1),
    (SELECT Name FROM grades LIMIT 2, 1),
    ...

Mit der gleichen Logik sieht unsere zweite Zeile so aus:

SELECT 'Marks',
    (SELECT Marks FROM grades LIMIT 0, 1),
    (SELECT Marks FROM grades LIMIT 1, 1),
    (SELECT Marks FROM grades LIMIT 2, 1),
    ...

Abrufen des Headers:

Wir müssen eine Zeile von MySQL erzeugen wie:

SELECT 'id', '1', '2', ... LIMIT 0, 0;

Um diese Zeile zu erhalten, verwenden wir CONCAT() und GROUP_CONCAT() Funktionen:

SELECT 'id', 
    (SELECT GROUP_CONCAT(CONCAT(' \'', id, '\'')) FROM grades)
LIMIT 0, 0;

und wir werden diese Zeile in einer neuen Variablen speichern:

SET @header = CONCAT('SELECT \'id\', ',
    (SELECT GROUP_CONCAT(CONCAT(' \'', id, '\'')) FROM grades),
    ' LIMIT 0, 0');

Erstellen der Linien:

Wir müssen zwei Abfragen wie die folgende erstellen:

SELECT 'Name',
    (SELECT Name FROM grades LIMIT 0, 1),
    (SELECT Name FROM grades LIMIT 1, 1),
    (SELECT Name FROM grades LIMIT 2, 1),
    ...

Da wir im Voraus nicht wissen, wie viele Zeilen unsere ursprüngliche Tabelle enthält, verwenden wir Variablen, um die verschiedenen LIMIT x, 1 zu generieren Aussagen. Sie können wie folgt erstellt werden:

SET @a = -1;
SELECT @a:[email protected]+1 FROM grades;

Mit diesem Snippet können wir unsere Unterabfragen erstellen:

SELECT GROUP_CONCAT(
    CONCAT(' (SELECT name FROM grades LIMIT ',
        @a:[email protected]+1,
        ', 1)')
    )
FROM grades

Was wir zusammen mit den Daten der ersten Spalte (das ist der Name der zweiten Spalte) in eine Variable mit dem Namen @line1 einfügen:

SET @a = -1;
SET @line1 = CONCAT(
    'SELECT \'Name\',',
    (
        SELECT GROUP_CONCAT(
            CONCAT(' (SELECT Name FROM grades LIMIT ',
                @a:[email protected]+1,
                ', 1)')
            )
        FROM grades
    ));

Wenn Sie der gleichen Logik folgen, lautet die zweite Zeile:

SET @a := -1;
SET @line2 = CONCAT(
    'SELECT \'Marks\',',
    (
        SELECT GROUP_CONCAT(
            CONCAT(' (SELECT Marks FROM grades LIMIT ',
                @a:[email protected]+1,
                ', 1)')
            )
        FROM grades
    ));

Alle kombinieren:

Unsere drei Variablen enthalten jetzt:

@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)

Wir müssen nur eine letzte Variable mit CONCAT() erstellen , als neue Abfrage vorbereiten und ausführen:

SET @query = CONCAT('(',
    @header,
    ') UNION (',
    @line1,
    ') UNION (',
    @line2,
    ')'
);

PREPARE my_query FROM @query;
EXECUTE my_query;

Gesamte Lösung:

(zum Testen und Nachschlagen):

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;

Ausgabe:

+-------+------+-------+
| id    | 1    | 2     |
+-------+------+-------+
| Name  | Ram  | Shyam |
| Marks | 45   | 87    |
+-------+------+-------+
2 rows in set (0.00 sec)

Abschlussgedanken:

  • Ich bin mir immer noch nicht sicher, warum Sie Zeilen in Spalten umwandeln müssen, und ich bin sicher, dass die von mir vorgestellte Lösung nicht die beste ist (in Bezug auf die Leistung).

  • Sie können meine Lösung sogar als Start verwenden und sie an eine Allzwecklösung anpassen, bei der die Tabellenspaltennamen (und die Anzahl der Zeilen) nicht bekannt sind, indem Sie information_schema verwenden .COLUMNS als Quelle, aber das geht wohl zu weit.

  • Ich bin fest davon überzeugt, dass es viel besser ist, die ursprüngliche Tabelle in ein Array zu stecken und dieses Array dann zu drehen, um so die Daten im gewünschten Format zu erhalten.