Domanda

I have a table with a date field. I need a query to group_concat the dates only if they are consecutive, otherwise return them individually.

So, for example , if my table has the following data:

+---------+--------------+
| user_id | checkin_date |
+---------+--------------+
|       1 | 2012-02-01   |
|       2 | 2012-03-01   |
|       3 | 2012-02-03   |
|       4 | 2012-02-02   |
+---------+--------------+

I need a query that would return the following results

+--------------------------+
| checkin_period           |
+--------------------------+
| 2012-02-01 - 2012-02-03  |
| 2012-03-01               |
+--------------------------+

As you can see, feb 1st, 2nd and 3rd have been grouped in 1 row (with only the first and last day being displayed), whereas March 1st is by itself...

I have no idea where to start!

Thanks in advance,

Alain

È stato utile?

Soluzione

SELECT
  CONCAT_WS(' - ',
    MIN(checkin_date),
    CASE WHEN MAX(checkin_date)>MIN(checkin_date) THEN MAX(checkin_date) END
  ) As time_interval
FROM (
  SELECT
    CASE WHEN checkin_date=@last_ci+INTERVAL 1 DAY THEN @n ELSE @n:=@n+1 END AS g,
    @last_ci := checkin_date As checkin_date
  FROM
    tablename, (SELECT @n:=0) r
  ORDER BY
    checkin_date
) s
GROUP BY
  g

Please see fiddle here.

Altri suggerimenti

You could increment a user variable @p only if the checkin_date is not consecutive with the prior row, that is if the date increases by more than 1 day.

SELECT IF(checkin_date <= @d + INTERVAL 1 DAY, @p, @p:=@p+1) AS p, @d:=checkin_date AS d
FROM (SELECT @p:=0, @d:='1900-01-01') _init, mytable 
ORDER BY checkin_date;

+------+------------+
| p    | d          |
+------+------------+
|    1 | 2012-02-01 |
|    1 | 2012-02-02 |
|    1 | 2012-02-03 |
|    2 | 2012-03-01 |
+------+------------+

Then use the above as a subquery, grouping by the p column, and return a string of the min to max range or else just one value if the count within the group is 1.

SELECT IF(COUNT(*) > 1, CONCAT(MIN(d), ' - ', MAX(d)), MAX(d)) AS date_range 
FROM (
  SELECT IF(checkin_date <= @d + INTERVAL 1 DAY, @p, @p:=@p+1) AS p, @d:=checkin_date AS d
  FROM (SELECT @p:=0, @d:='1900-01-01') _init, mytable 
  ORDER BY checkin_date) AS t 
GROUP BY p;

+-------------------------+
| date_range              |
+-------------------------+
| 2012-02-01 - 2012-02-03 |
| 2012-03-01              |
+-------------------------+
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top