sql >> Database teknologi >  >> RDS >> Mysql

Vælg MYSQL rækker, men rækker i kolonner og kolonner i rækker

Med en fast og kendt kolonne, se her hvordan man gør det (jeg tog mig den frihed at navngive tabellen "karakterer"):

Generel idé:

At skabe en forening af forskellige forespørgsler og udføre den.

Da du har brug for faktiske data som kolonneoverskrifter, vil den første del af foreningen se sådan ud:

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

Alene denne forespørgsel vil duplikere resultatet, derfor skal vi fortælle MySQL, at vi skal have 0 rækker ved at tilføje LIMIT 0, 0 .

Vores første række i foreningen vil indeholde 'Name' , samt alle data fra kolonnen "Navn" i tabellen. For at få den linje har vi brug for en forespørgsel som:

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

Ved at bruge den samme logik vil vores anden række se ud som:

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

Hent headeren:

Vi skal producere en række fra MySQL som:

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

For at få den linje vil vi bruge CONCAT() og GROUP_CONCAT() funktioner:

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

og vi vil gemme den linje i en ny variabel:

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

Oprettelse af linjerne:

Vi skal oprette to forespørgsler som følgende:

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

Da vi ikke på forhånd ved, hvor mange rækker der er i vores oprindelige tabel, vil vi bruge variabler til at generere de forskellige LIMIT x, 1 udsagn. De kan fremstilles ved hjælp af følgende:

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

Ved at bruge dette uddrag kan vi oprette vores underforespørgsler:

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

Som vi vil sætte ind i en variabel navne @line1, sammen med den første kolonne data (som er den anden kolonnes navn):

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

Ved at følge den samme logik vil den anden linje være:

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

Kombiner dem alle:

Vores tre variabler indeholder 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 skal blot oprette en endelig variabel ved hjælp af CONCAT() , klargør den som en ny forespørgsel og kør den:

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

PREPARE my_query FROM @query;
EXECUTE my_query;

Hele løsningen:

(til test og reference):

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;

Output:

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

Afsluttende tanker:

  • Jeg er stadig ikke sikker på, hvorfor du skal transformere rækker til kolonner, og jeg er sikker på, at den løsning, jeg præsenterede, ikke er den bedste (i forhold til ydeevne).

  • Du kan endda bruge min løsning som en start og tilpasse den til en generel løsning, hvor tabelkolonnenavnene (og antallet af linjer) ikke er kendt, ved hjælp af information_schema .COLUMNS som kilde, men det er vist bare at gå for vidt.

  • Jeg er overbevist om, at det er meget bedre at placere den originale tabel i et array og derefter rotere det array, og dermed få dataene i det ønskede format.



  1. Valg af poster efter dato ->=NU(), MySQL

  2. Kassér millisekunddelen fra tidsstemplet

  3. hvordan man konfigurerer dvalekonfigurationsfil til sql-server

  4. Konvertering af et tal til et ord i Mysql