MySQL use ExtractValue(XML, 'Value/Values') to get all multiple values (split one column into rows)

前端 未结 1 1806
粉色の甜心
粉色の甜心 2021-01-13 00:20

I have a non-normal field containing multiple values because it is Xml data that wasn\'t intended to be queried, until now. Can MySQL split this xml column into multiple row

相关标签:
1条回答
  • 2021-01-13 01:08

    No. You must solve this just like other mysql split column problems.

    • Can MySQL split a column?
    • Mysql string split

    I.e. Specifically based on this answer

    DROP FUNCTION IF EXISTS STRSPLIT;
    DELIMITER $$
    CREATE FUNCTION STRSPLIT($Str VARCHAR(20000), $delim VARCHAR(12), $pos INTEGER) 
        RETURNS VARCHAR(20000)
    BEGIN
        DECLARE output VARCHAR(20000);
    
        SET output = REPLACE(SUBSTRING(SUBSTRING_INDEX($Str, $delim, $pos)
                     , LENGTH(SUBSTRING_INDEX($Str, $delim, $pos - 1)) + 1)
                     , $delim
                     , '');
    
        IF output = '' 
            THEN SET output = null;
        END IF;
    
        RETURN output;
    END $$
    

    You can iterate through the values like so

    DROP PROCEDURE IF EXISTS GetNameValues $$
    CREATE PROCEDURE GetNameValues()
    BEGIN
        DECLARE i INTEGER;
    
        DROP TEMPORARY TABLE IF EXISTS TempList;
        CREATE TEMPORARY TABLE TempList(
            `Name` VARCHAR(256) COLLATE utf8_unicode_ci NOT NULL,
            `ValueList` VARCHAR(20000) COLLATE utf8_unicode_ci NOT NULL
        );
        DROP TEMPORARY TABLE IF EXISTS Result;
        CREATE TEMPORARY TABLE Result(
            `Name` VARCHAR(256) COLLATE utf8_unicode_ci NOT NULL,
            `Value` VARCHAR(128) COLLATE utf8_unicode_ci NOT NULL
        );
    
        INSERT INTO
            TempList
        SELECT
            I.`Name`,
            ExtractValue(Xml,'/Xml/Values/Value') AS ValueList
        FROM
            Item AS I
        WHERE
            I.TypeID = 'A'
        ;
    
        SET i = 1;
        REPEAT
            INSERT INTO
                Result
            SELECT
                `Name`,
                CAST(STRSPLIT(ValueList, ' ', i) AS CHAR(128)) AS Value
            FROM
                TempList
            WHERE 
                CAST(STRSPLIT(ValueList, ' ', i) AS CHAR(128)) IS NOT NULL
            ;
    
            SET i = i + 1;
            UNTIL ROW_COUNT() = 0
        END REPEAT;
    
        SELECT * FROM Result ORDER BY `Name`;
    END $$
    
    DELIMITER ;
    
    CALL GetNameValues();
    

    Hope this helps someone one day.

    0 讨论(0)
提交回复
热议问题