sql >> Databasteknik >  >> RDS >> Mysql

Välj MYSQL-rader men rader i kolumner och kolumner i rader

Med en fast och känd kolumn, så här gör du (jag tog mig friheten att namnge tabellen "betyg"):

Allmän idé:

Att skapa en förening av olika frågor och köra den.

Eftersom du behöver faktiska data som kolumnrubriker kommer den första delen av föreningen att se ut så här:

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

Enbart den frågan kommer att duplicera resultatet, därför måste vi tala om för MySQL att vi måste ha 0 rader genom att lägga till LIMIT 0, 0 .

Vår första rad i förbundet kommer att innehålla 'Name' , samt all data från kolumnen "Namn" i tabellen. För att få den raden behöver vi en fråga som:

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

Med samma logik kommer vår andra rad att se ut så här:

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

Hämta rubriken:

Vi måste producera en rad från MySQL som:

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

För att få den raden använder vi CONCAT() och GROUP_CONCAT() funktioner:

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

och vi kommer att lagra den raden i en ny variabel:

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

Skapa raderna:

Vi måste skapa två frågor som följande:

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

Eftersom vi inte i förväg vet hur många rader det finns i vår ursprungliga tabell kommer vi att använda variabler för att generera de olika LIMIT x, 1 uttalanden. De kan tillverkas med följande:

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

Med det här utdraget kan vi skapa våra underfrågor:

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

Vilket vi lägger in i en variabel namnger @line1, tillsammans med den första kolumndata (som är den andra kolumns namn):

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

Genom att följa samma logik blir den andra raden:

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

Kombinerar dem alla:

Våra tre variabler innehåller nu:

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

Vi behöver bara skapa en slutlig variabel med CONCAT() , förbered den som en ny fråga och kör den:

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

PREPARE my_query FROM @query;
EXECUTE my_query;

Hela lösningen:

(för testning och referens):

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;

Utdata:

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

Avslutande tankar:

  • Jag är fortfarande inte säker på varför du behöver omvandla rader till kolumner, och jag är säker på att lösningen jag presenterade inte är den bästa (i termer av prestanda).

  • Du kan till och med använda min lösning som en början och anpassa den till en allmän lösning där tabellkolumnnamnen (och antalet rader) inte är kända, med information_schema .COLUMNS som källa, men jag antar att det bara går för långt.

  • Jag är övertygad om att det är mycket bättre att placera den ursprungliga tabellen i en array och sedan rotera den arrayen och på så sätt få data i önskat format.



  1. Kan inte få antalet rader och hämta när du använder MySQLi-förberedd sats

  2. Använda PostgreSQL logisk replikering för att upprätthålla en alltid uppdaterad läs-/skriv-TEST-server

  3. Vilken är den bästa MySQL-samlingen för tyska språket

  4. Hur man vadderar en sträng med ledande/släpande tecken i MySQL – LPAD(), RPAD()