Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Zwei Spalten zusammenführen, mehrere Zeilen ignorieren und Duplikate ignorieren - MySQL

Sie könnten es mit dieser Anweisung tun (nein, es sieht nicht gut aus), vorausgesetzt, der Name Ihrer Tabelle ist 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 = ''
;

Demo der SELECT-Anweisung

Erklärung

Grundsätzlich habe ich die Methode angepasst von peterm um die Aufteilung zu erledigen. Ich musste den äußeren * entfernen zuerst durch TRIM.

Um den leeren String als Spaltenwert zuzulassen, habe ich das CASE-Konstrukt hinzugefügt, um solche Werte zu eliminieren. Wenn Ihre Spalte stattdessen NULL-Werte enthält, können Sie CASE durch

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

und

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

Die UNION (ohne das Schlüsselwort ALL) dieses Konstrukts gibt uns die Liste der unterschiedlichen Farbwerte und mit GROUP BY id und GROUP_CONCAT erhalten wir die *-getrennte Werteliste. Zuletzt fügen wir einen führenden und einen abschließenden * hinzu Ihren Anforderungen entsprechen.

Für das Update müssen Sie das select so ändern, dass es nur eine Spalte mit einer Zeile zurückgibt (mit der where-Klausel).

Hinweis

Wie von peterm angegeben, erlaubt dies bis zu 100 Werte in Ihrer Werteliste. Ich glaube nicht, dass du mehr brauchen wirst, aber wenn du willst, dann musst du die Generierung der Zahlen an deine Bedürfnisse anpassen.