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

Sloučit dva sloupce, více řádků ignorovat duplikáty - MySQL

Můžete to udělat pomocí tohoto prohlášení (ne, nevypadá to hezky), za předpokladu, že název vaší tabulky je example :

UPDATE
    example e1
SET
    e1.type_a = (
        SELECT
            CONCAT('*', GROUP_CONCAT(DISTINCT n1.value ORDER BY n1.value SEPARATOR '*'), '*') as type_a
        FROM ( 
            SELECT
                id, 
            CASE 
                WHEN SUBSTRING_INDEX(SUBSTRING_INDEX(TRIM(BOTH '*' FROM e.type_a), '*', n.n), '*', -1) = '' THEN NULL
                ELSE SUBSTRING_INDEX(SUBSTRING_INDEX(TRIM(BOTH '*' FROM e.type_a), '*', n.n), '*', -1)
            END value
            FROM example e CROSS JOIN (
                SELECT 
                    a.N + b.N * 10 + 1 AS n
                FROM
                    (SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a
                   ,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b
                ORDER BY n
            ) n
            WHERE 
                n.n <= 1 + (LENGTH(e.type_a) - LENGTH(REPLACE(e.type_a, '*', '')))
            UNION
            SELECT
                id, 
            CASE 
                WHEN SUBSTRING_INDEX(SUBSTRING_INDEX(TRIM(BOTH '*' FROM e.type_b), '*', n.n), '*', -1) = '' THEN NULL
                ELSE SUBSTRING_INDEX(SUBSTRING_INDEX(TRIM(BOTH '*' FROM e.type_b), '*', n.n), '*', -1)
            END value
            FROM example e CROSS JOIN (
                SELECT 
                    a.N + b.N * 10 + 1 AS n
                FROM
                    (SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a
                   ,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b
                ORDER BY n
            ) n
            WHERE 
                n.n <= 1 + (LENGTH(e.type_b) - LENGTH(REPLACE(e.type_b, '*', '')))
        ) n1
        WHERE 
            n1.id = e1.id
        GROUP BY 
            id
    ),
    e1.type_b = ''
;

Ukázka příkazu SELECT

Vysvětlení

V podstatě jsem upravil metodu z peterm aby bylo rozdělení hotovo. Musel jsem odstranit vnější * nejprve pomocí TRIM.

Abych povolil prázdný řetězec jako hodnotu sloupce, přidal jsem konstrukci CASE, abych takové hodnoty odstranil. Pokud má váš sloupec místo toho hodnoty NULL, můžete CASE nahradit výrazem

SUBSTRING_INDEX(SUBSTRING_INDEX(TRIM(BOTH '*' FROM e.type_a), '*', n.n), '*', -1)

a

SUBSTRING_INDEX(SUBSTRING_INDEX(TRIM(BOTH '*' FROM e.type_a), '*', n.n), '*', -1)

UNION (bez klíčového slova ALL) tohoto konstruktu nám dá seznam odlišných hodnot barev a pomocí GROUP BY id a GROUP_CONCAT získáme * seznam oddělených hodnot. Nakonec přidáme úvodní a koncové * podle vašich požadavků.

Pro aktualizaci musíte upravit výběr tak, aby vrátil pouze jeden sloupec s jedním řádkem (s klauzulí where).

Poznámka

Jak uvedl peterm, umožní to až 100 hodnot ve vašem seznamu hodnot. Nevěřím, že budete potřebovat více, ale pokud ano, musíte si generování čísel přizpůsobit svým potřebám.




  1. Připojovací řetězec ODBC 5.1 pro MySQL s přístupem pouze pro čtení

  2. Jak používat regex v MySQL?

  3. Uložení výsledků připraveného příkazu jako tabulky v mysql?

  4. Trendy ScyllaDB – Jak uživatelé nasazují databázi velkých dat v reálném čase