Converting delimited string to multiple values in mysql

后端 未结 5 1816
逝去的感伤
逝去的感伤 2020-12-11 18:40

I have a mysql legacy table which contains an client identifier and a list of items, the latter as a comma-delimited string. E.g. \"xyz001\", \"foo,bar,baz\". T

5条回答
  •  -上瘾入骨i
    2020-12-11 19:04

    Overview

    • This is to add on to the answers that suggest using UNION

    Context

    • MySQL 5.7

    Problem

    • User xyz001epo wishes to convert a single-row delimited string into multiple rows

    Screenshot

    • The goal is to change BEFORE into AFTER

    Solution

    • if the maximum number of items per single-row delimited string is known in advance, this can be accomplished using a UNION query over the known number of elements
    • in this example we ignore the first element as it is considered superfluous to the output result (e.g., you have a case where all delimited strings start with some throw-away token such as http:// or something similar)

    Sample code

    
    SELECT
      tta.*
    FROM
    (
        SELECT
          rowid                                                              as txtname
          ,SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(fld005,'/'),'/',2),'/',-1)  as txtvalu
        FROM zzdemo_uu112pingasrcdata
    UNION
        SELECT
          rowid                                                              as txtname
          ,SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(fld005,'/'),'/',3),'/',-1)  as txtvalu
        FROM zzdemo_uu112pingasrcdata
    UNION
        SELECT
          rowid                                                              as txtname
          ,SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(fld005,'/'),'/',4),'/',-1)  as txtvalu
        FROM zzdemo_uu112pingasrcdata
    UNION
        SELECT
          rowid                                                              as txtname
          ,SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(fld005,'/'),'/',5),'/',-1)  as txtvalu
        FROM zzdemo_uu112pingasrcdata
    UNION
        SELECT
          rowid                                                              as txtname
          ,SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(fld005,'/'),'/',6),'/',-1)  as txtvalu
        FROM zzdemo_uu112pingasrcdata
    UNION
        SELECT
          rowid                                                              as txtname
          ,SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(fld005,'/'),'/',7),'/',-1)  as txtvalu
        FROM zzdemo_uu112pingasrcdata
    UNION
        SELECT
          rowid                                                              as txtname
          ,SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(fld005,'/'),'/',8),'/',-1)  as txtvalu
        FROM zzdemo_uu112pingasrcdata
    UNION
        SELECT
          rowid                                                              as txtname
          ,SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(fld005,'/'),'/',9),'/',-1)  as txtvalu
        FROM zzdemo_uu112pingasrcdata
    UNION
        SELECT
          rowid                                                              as txtname
          ,SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(fld005,'/'),'/',10),'/',-1) as txtvalu
        FROM zzdemo_uu112pingasrcdata
    ) as tta
    WHERE 1
      AND (txtvalu is not null)
      AND (txtvalu <> '')
    ;;;
    
    

    Complete example

    • a complete example is available at the public lab space for this answer

    Rationale

    • for use when the transformation must be done inside MySQL instead of on the application layer
    • for use when the specific user account does not have permissions to create new functions in MySQL for security or other reasons

    Pitfalls

    • this solution assumes a known maximum number of items per delimited string which is not always an option
    • this solution requires a trailing delimiter at the end of the delimited string, or else it will not produce the desired result
    • this approach is not aesthetically pleasing, it will hurt some eyes and it will hurt some feelings

提交回复
热议问题