Search code examples
mysqlsqlgroup-concat

How to group by / group_concat each set of results?


Image we have a table like this:

table1

+----------+----------+--------+------------+
| position | epoc     | name   | value      |
+----------+----------+--------+------------+
|    1     |    1     |   A    |        v01 |
|    1     |    1     |   B    |        v02 |
|    1     |    1     |   C    |        v03 |
|    1     |    2     |   A    |        v04 |
|    1     |    2     |   B    |        v05 |
|    1     |    2     |   C    |        v06 |
|    1     |    3     |   A    |        v07 |
|    1     |    3     |   B    |        v08 |
|    1     |    3     |   C    |        v09 |
|    1     |    4     |   A    |        v10 |
|    1     |    4     |   B    |        v11 |
|    1     |    4     |   C    |        v12 |
|    2     |    5     |   A    |        v13 |
|    2     |    5     |   B    |        v14 |
|    2     |    5     |   C    |        v15 |
|    2     |    6     |   A    |        v16 |
|    2     |    6     |   B    |        v17 |
|    2     |    6     |   C    |        v18 |
|    2     |    7     |   A    |        v19 |
|    2     |    7     |   B    |        v20 |
|    2     |    7     |   C    |        v21 |
|    2     |    8     |   A    |        v22 |
|    2     |    8     |   B    |        v23 |
|    2     |    8     |   C    |        v24 |
+----------+----------+--------+------------+

I want to be able to get this table:

table2

+----------+--------------------+
| position | value              |
+----------+--------------------+
|    1     |    v01,v02,v04,v05 |
|    2     |    v13,v14,v16,v17 | 
+----------+--------------------+

the conditions are:

  • JUST the "value" of rows with "name" A OR B;
  • JUST "epocs" that are the first 2 unique results in "position" (epoc 3,4,7,8 are discarded)
  • GROUP by table1 position (for each position I want the concat of the values that match previous conditions)

Solution

  • This might be what you are looking for:

    select position, 
      group_concat(value order by overall_row_num) value
    from
    (
      select position,
          name,
          value,
          epoc,
           @num := if(@position = `position`, @num + 1, 1) as group_row_number,
           @position := `position` as dummy, 
          overall_row_num
      from
      (
        select position, name, 
          epoc, 
          value,
          @rn:=@rn+1 overall_row_num
        from t1, (SELECT @rn:=0) r
        where name in ('A', 'B')
        order by position, epoc
      ) x
      order by overall_row_num
    ) x1
    where group_row_number <= 4
    group by position
    

    See SQL Fiddle with demo