4

I have been searching for hours without a decent answer.

I want to transform this table:


Client_id    Date
-----------  ------------  
1            2013-02-03    
1            2013-02-10
1            2013-05-12
2            2013-02-03
2            2013-07-15

To:


Client_id    Date1          Date2         Date3         Date4, Date5, Date6...
-----------  ------------   ------------  ------------  ------------
1            2013-02-03     2013-02-10    2013-05-12
2            2013-02-03     2013-07-15
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
wizard
  • 583
  • 2
  • 9
  • 26
  • Do you know the max number of dates or is it infinite? If you know the number, you can do this with pure SQL. If not, you'll need to use dynamic sql. – sgeddes Feb 05 '13 at 19:10
  • 1
    Issues of data display are generally best handled at the application level, e.g. with a bit of PHP. Failing that, just rotate your monitor through 90 degrees ;-) – Strawberry Feb 05 '13 at 19:21
  • basically 5 dates max. – wizard Feb 05 '13 at 19:29
  • possible duplicate of [MySQL pivot row into dynamic number of columns](http://stackoverflow.com/questions/12004603/mysql-pivot-row-into-dynamic-number-of-columns) – RichardTheKiwi May 03 '13 at 09:19
  • Possible duplicate of [MySQL pivot table query with dynamic columns](http://stackoverflow.com/questions/12598120/mysql-pivot-table-query-with-dynamic-columns) – Alexander May 14 '17 at 09:41

1 Answers1

12

In order to get this result, you will want to pivot the data. MySQL does not have a pivot function but you can use an aggregate function with a CASE expression.

If the number of dates is known, then you can hard-code the query:

select client_id,
  max(case when rownum = 1 then date end) Date1,
  max(case when rownum = 2 then date end) Date2,
  max(case when rownum = 3 then date end) Date3
from
(
  select client_id,
    date,
    @row:=if(@prev=client_id, @row,0) + 1 as rownum,
    @prev:=client_id 
  from yourtable, (SELECT @row:=0, @prev:=null) r
  order by client_id, date
) s
group by client_id
order by client_id, date

See SQL Fiddle with Demo

I implemented user variables to assign a row number to each record within the client_id group.

If you have an unknown number of dates, then you will need to use a prepared statement to create the sql dynamically:

SET @sql = NULL;
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'MAX(CASE WHEN rownum = ',
      rownum,
      ' THEN date END) AS Date_',
      rownum
    )
  ) INTO @sql
from
(
  select client_id,
    date,
    @row:=if(@prev=client_id, @row,0) + 1 as rownum,
    @prev:=client_id 
  from yourtable, (SELECT @row:=0) r
  order by client_id, date
) s
order by client_id, date;


SET @sql 
  = CONCAT('SELECT client_id, ', @sql, ' 
           from
           (
             select client_id,
               date,
               @row:=if(@prev=client_id, @row,0) + 1 as rownum,
               @prev:=client_id 
             from yourtable, (SELECT @row:=0) r
             order by client_id, date
           ) s
           group by client_id
           order by client_id, date');

PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

See SQL Fiddle with Demo.

They both give the result:

| CLIENT_ID |                          DATE_1 |                          DATE_2 |                     DATE_3 |
--------------------------------------------------------------------------------------------------------------
|         1 | February, 03 2013 00:00:00+0000 | February, 10 2013 00:00:00+0000 | May, 12 2013 00:00:00+0000 |
|         2 | February, 03 2013 00:00:00+0000 |     July, 15 2013 00:00:00+0000 |                     (null) |
Taryn
  • 242,637
  • 56
  • 362
  • 405
  • u deserve +100 from me :) , u genius in sql :) – echo_Me Feb 05 '13 at 19:29
  • @wizard You have to be able to tell the aggregate what date to turn into the column that is why the `row number` is so important. Otherwise it will not know which one to select in each column – Taryn Feb 05 '13 at 19:32
  • @bluefeet Works excellent! Many thanks! Where I can learn more about complex sql like that? – wizard Feb 05 '13 at 20:23
  • @wizard I am glad that it works for you. I learned from answering and reviewing questions on this website. It is a great resource for so many different things. – Taryn Feb 05 '13 at 20:26
  • @wizard By the way, welcome to stack overflow. In the event you are not sure how things work, if you find any of the answers to your questions helpful then be sure to accept the answer via the checkmark to the left of it. It will help future visitors to the site and you get site rep for accepting. :) – Taryn Feb 05 '13 at 20:27