how to transform comma separated column into multiples rows in db2

前端 未结 4 641
野趣味
野趣味 2020-12-10 20:38

I have the following table (the number of the references is variable):

Id | FK_ID| Reference |
-----------------------
1    2100   GI2, GI32
2    2344   GI56         


        
相关标签:
4条回答
  • 2020-12-10 20:52

    i did something similar with posstr(trim(ROW, '[DELIMITER]')), LENGTH .. like:

    Table
    NAME
    ---------------------
    Martin, Example
    
    SELECT         
        CASE WHEN POSSTR(NAME, ',') > 0
             THEN SUBSTR(TRIM(NAME), POSSTR(TRIM(NAME), ',') + 1), LENGTH(TRIM(NAME)) - POSSTR(TRIM(NAME),',')))
             ELSE 'ERROR'
        END
    FROM ...
    UNION ALL
    .. 
    
    Result: Example
    

    but not tested,.. there might then be empty resultsets, they must be deletede afterwards..

    0 讨论(0)
  • 2020-12-10 21:00

    1st Off i don't know why so many people say you shouldn't be storing data this/that way etc when you are doing ETL. They clearly don't understand what an ETL developer actually does for a job. Which is they rarely control the format of the data they receive but have to make it behave better when delivered to its destination. Ok enough venting: Here is what i suggest.

    I would take the delimited list and turn it into a Values clause for a dynamic SQL Statement to select from or use it to dynamically create a table or view to use... the possibilities after getting the pivot are many and easy. Here is a small code snippet that you could easily embed in a Stored Proc... This assumes a recent version of DB2 (hopefully last 4/5 years)....

    declare sDelimitString as Varchar(500);
    declare sValues as Varchar(1000);
    set sDelimitString = 'Data 1,Data 2,Data 3';
    set sValues = ''' Values((' || Replace((sDelimitString,',','''),(''') || '))'' as PIVOT_DATA(SOME_COLUMN_NAME) ';  
    declare cCur Cursor with return for aStmt;
    set sSQL = Select PIVOT_DATA.SOME_COLUMN_NAME FROM ' || sValues;
    prepare aStmt from sSQL;
    open cCur;
    

    The idea is to use the values statment like "Select C1 From (Values(1),(2),(3)) as T1(C1)" which pivots. You could even make this part of a larger SQL statement that has your full select in it and dynamically return results, insert the data into a tmp table, or dynamically create a view etc...

    Now DB2 is just weird with Dynamic cursors vs oracle, sql server or pretty much any other database. In my experience the declare cCur line has to be the last "Declare" statement in the stored proc otherwise procs won't compile and nowhere on google does it tell you why.... This was painful and shouldn't be but i've found the same pain many times in db2 in other areas. Again once you have the pivot you can do anything with it. And the sSQL doesn't have to be a select statement it could be a command to dynamically build a temp table or view to pull from ... options are limitless after the pivot. Best of luck... I know its late.. but i wasn't a big fan of the solutions or commentary here.

    0 讨论(0)
  • 2020-12-10 21:04

    You really should not be storing data like this. Fortunately, there is a way to undo the damage with recursive SQL, something along these lines:

    WITH unpivot (lvl, id, fk_ref, reference, tail) AS (  
      SELECT 1, id, fk_ref,     
             CASE WHEN LOCATE(',',reference) > 0 
                  THEN TRIM(LEFT(reference, LOCATE(',',reference)-1))
                  ELSE TRIM(reference) 
             END,    
             CASE WHEN LOCATE(',',reference) > 0 
                  THEN SUBSTR(reference, LOCATE(',',reference)+1)    
                  ELSE '' 
             END  
      FROM yourtable  
      UNION ALL  
      SELECT lvl + 1, id, fk_ref,     
             CASE WHEN LOCATE(',', tail) > 0 
                  THEN TRIM(LEFT(tail, LOCATE(',', tail)-1))    
                  ELSE TRIM(tail) 
             END,    
             CASE WHEN LOCATE(',', tail) > 0 
                  THEN SUBSTR(tail, LOCATE(',', tail)+1)    
                  ELSE '' 
             END
      FROM unpivot 
      WHERE lvl < 100 AND tail != '')
      SELECT id, fk_ref, reference FROM unpivot
    

    PS. Not tested.

    0 讨论(0)
  • 2020-12-10 21:07

    I posted a generic solution for this type of transform under Split comma separated entries to rows

    To view results for this sample data, replace the session data with:

    INSERT INTO session.sample_data SELECT 1, 2100, 'GI2,GI32' FROM sysibm.sysdummy1;
    INSERT INTO session.sample_data SELECT 2, 2344, 'GI56' FROM sysibm.sysdummy1;
    

    Results:

    ID  OTHERID DATA
    1   2100    GI2
    1   2100    GI32
    2   2344    GI56
    
    0 讨论(0)
提交回复
热议问题