sql >> Database >  >> RDS >> Mysql

Voeg twee kolommen samen, meerdere rijen en negeer duplicaten - MySQL

Je zou het met deze verklaring kunnen doen (nee, het ziet er niet goed uit), ervan uitgaande dat de naam van je tabel example is :

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 = ''
;

Demo van de SELECT-instructie

Uitleg

In principe heb ik de methode aangepast van peterm om de splitsing gedaan te krijgen. Ik moest de buitenste * . verwijderen eerst door TRIM.

Om de lege string als kolomwaarde toe te staan, heb ik de CASE-constructie toegevoegd om dergelijke waarden te elimineren. Als uw kolom in plaats daarvan NULL-waarden heeft, kunt u de CASE vervangen door

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

en

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

De UNION (zonder het sleutelwoord ALL) van deze constructie geeft ons de lijst met verschillende kleurwaarden en met GROUP BY id en GROUP_CONCAT krijgen we de * gescheiden waardenlijst. Als laatste voegen we een voorloop en een naloop toe * om aan uw eisen te voldoen.

Voor de update moet je de select aanpassen, zodat deze slechts één kolom met één rij retourneert (met de where-clausule).

Opmerking

Zoals aangegeven door Peterm zal dit tot 100 waarden in uw lijst met waarden toestaan. Ik geloof niet dat je meer nodig zult hebben, maar als je wilt, dan moet je het genereren van de cijfers aanpassen aan je behoeften.




  1. Hiërarchische lijst met typen triggergebeurtenissen in SQL Server 2017

  2. Door komma's gescheiden waarden in Oracle

  3. Gedrag van SQL Server 2016-queryplan voor tijdelijke tabellen

  4. Beste manier om geordende lijsten op te slaan in een database?