sql >> Databáze >  >> RDS >> Mysql

Vyberte řádky MYSQL, ale řádky do sloupců a sloupec do řádků

S pevnými a známými sloupci, zde je návod, jak to udělat (dovolil jsem si pojmenovat tabulku "známky"):

Obecná myšlenka:

Chcete-li vytvořit spojení různých dotazů a provést je.

Protože potřebujete skutečná data jako záhlaví sloupců, první část sjednocení bude vypadat takto:

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

Tento dotaz sám o sobě bude duplikovat výsledek, proto musíme říci MySQL, že potřebujeme mít 0 řádků přidáním LIMIT 0, 0 .

Náš první řádek sjednocení bude obsahovat 'Name' , stejně jako všechna data ze sloupce "Název" tabulky. K získání tohoto řádku potřebujeme dotaz jako:

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

Pomocí stejné logiky bude náš druhý řádek vypadat takto:

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

Získání záhlaví:

Potřebujeme vytvořit řádek z MySQL jako:

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

K získání tohoto řádku použijeme CONCAT() a GROUP_CONCAT() funkce:

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

a tento řádek uložíme do nové proměnné:

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

Vytvoření čar:

Potřebujeme vytvořit dva dotazy, jako je tento:

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

Protože předem nevíme, kolik řádků je v naší původní tabulce, použijeme proměnné ke generování různých LIMIT x, 1 prohlášení. Lze je vyrobit pomocí následujícího:

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

Pomocí tohoto úryvku můžeme vytvořit naše poddotazy:

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

Které vložíme do proměnné name @line1 spolu s daty prvního sloupce (což je název druhého sloupce):

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

Při dodržení stejné logiky bude druhý řádek:

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

Kombinace všech:

Naše tři proměnné nyní obsahují:

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

Potřebujeme pouze vytvořit konečnou proměnnou pomocí CONCAT() , připravte jej jako nový dotaz a spusťte jej:

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

PREPARE my_query FROM @query;
EXECUTE my_query;

Celé řešení:

(pro testování a referenci):

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;

Výstup:

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

Závěrečné myšlenky:

  • Stále si nejsem jistý, proč potřebujete transformovat řádky na sloupce, a jsem si jistý, že řešení, které jsem představil, není nejlepší (z hlediska výkonu).

  • Moje řešení můžete dokonce použít jako začátek a přizpůsobit je obecnému řešení, kde názvy sloupců tabulky (a počet řádků) nejsou známy, pomocí information_schema .COLUMNS jako zdroj, ale myslím, že to zachází příliš daleko.

  • Pevně ​​věřím, že je mnohem lepší vložit původní tabulku do pole a poté toto pole otočit, čímž získáme data v požadovaném formátu.



  1. Vrátit dotaz z funkce?

  2. Výjimka mySQL:Nelze se připojit k žádnému ze zadaných hostitelů MySQL. přes C#

  3. PHP- vkládání binárních dat do mysql pomocí připravených příkazů

  4. Shromažďování přírůstkových statistik v 11g