Search code examples
mysqlsqljoindynamic-pivot

SQL join to join values in primary table with child table values as different columns in a single row


I have a survey_datas table contain data's as like this

survey_data_id  | title
1               | Paul 
3               | Anna 
4               | Alan 

Another table project_playlist_indexes contain the data's like this

survey_id  |survey_data_id  | favorite
1          | 1              | 22.10
2          | 1              | 24.00
3          | 3              | 12.00

I want to join the survey_datas table with the project_playlist_indexes table so that values contained in the project_playlist_indexes table with same survey_data_id as survey_datas table should get as favorite time1 , favorite time 2, ... favorite time n , the result table I like to get is like this

survey_data_id  |title | favorite_time1 | favorite_time2
            1   | paul | 22.10          |24.00
            3   | anna | 12.00          | null
            4   | alan | null           | null

Currently I am using the query

SELECT s.*,GROUP_CONCAT(pi.favorite) ,pi.*
FROM survey_datas s
LEFT JOIN  project_playlist_indexes pi 
ON pi.survey_data_id = s.survey_data_id  
GROUP BY pi.survey_data_id

but the favorite values is getting in a single field I want it to be in different columns. How can I do this


Solution

  • You can do it by executing a dynamic sql query. What I have done is, first given a row number based on the survey_data_id column. Then selected each row number item as each column group by survey_data_id. Don't know how efficient the code is.

    Query

    set @query = null;
    select
      group_concat(distinct
        concat(
          'max(case when `rn` = ',
          `rn`,
          ' then `favorite` end) as `favorite', `rn` , '`'
        )
      ) into @query
    from (
      select `survey_id`, `survey_data_id`, `favorite`, (
        case `survey_data_id` when @curA 
        then @curRow := @curRow + 1 
        else @curRow := 1 and @curA := `survey_data_id` end 
      ) as `rn`
      from `project_playlist_indexes` t, 
      (select @curRow := 0, @curA := '') r 
      order by `survey_data_id`, `survey_data_id`
    ) t;
    
    set @query = concat('select t2.`survey_data_id`, t2.`title`,', 
                    @query,
                  ' from (select `survey_id`, `survey_data_id`, `favorite`, (
                  case `survey_data_id` when @curA 
                  then @curRow := @curRow + 1 
                  else @curRow := 1 and @curA := `survey_data_id` end 
                  ) as `rn`
                  from `project_playlist_indexes` t, 
                  (select @curRow := 0, @curA := '''') r 
                  order by `survey_data_id`, `survey_data_id`) t1
                  right join `survey_datas` t2
                  on t1.survey_data_id = t2.`survey_data_id`
                  group by t1.`survey_data_id`
                  order by t2.`survey_data_id`;'
         );
    
    prepare stmt from @query;
    execute stmt;
    deallocate prepare stmt;
    

    Find a demo here