Склеивание периодов в одном запросе

4you

еееххххх....
Склеивание периодов в одном запросе

Ув. знатоки подскажите возможно ли.
Имею таблицу вида:

PHP:
+----------------+----------------+--------------------+------------------+
| ID             | USER_ID        | PERIOD_START       | PERIOD_END       |
+----------------+----------------+--------------------+------------------+
| 1              | 1              | 2007-01-15         | 2007-01-30       |
+----------------+----------------+--------------------+------------------+
| 2              | 2              | 2007-01-10         | 2007-01-22       |
+----------------+----------------+--------------------+------------------+
| 3              | 2              | 2007-01-23         | 2007-02-10       |
+----------------+----------------+--------------------+------------------+
| 4              | 3              | 2007-01-01         | 2007-02-20       |
+----------------+----------------+--------------------+------------------+
Возможно ли получить при запросе всего 3 строки. Имеется ввиду что если у одного пользователя периоды идут друг за другом (начало 2-ого периода это конец первого периода) то выводим один общий большой период, т.е. в данном примере результат был бы таким:

PHP:
+----------------+----------------+--------------------+------------------+
| ID             | USER_ID        | PERIOD_START       | PERIOD_END       |
+----------------+----------------+--------------------+------------------+
| 1              | 1              | 2007-01-15         | 2007-01-30       |
+----------------+----------------+--------------------+------------------+
| 2              | 2              | 2007-01-10         | 2007-02-10       |
+----------------+----------------+--------------------+------------------+
| 4              | 3              | 2007-01-01         | 2007-02-20       |
+----------------+----------------+--------------------+------------------+
Заранее пасиб
 

alpine

Новичок
4you
- у тебя периоды идут именно подряд "без пробоев" для одного пользователя ?
- у тебя тип полей PERIOD_START и PERIOD_END - DATE ?
- что такое поле ID ?
 

4you

еееххххх....
Автор оригинала: alpine
4you
- у тебя периоды идут именно подряд "без пробоев" для одного пользователя ?

нет, не факт. могут быть разбросаны по таблице

- у тебя тип полей PERIOD_START и PERIOD_END - DATE ?
да

- что такое поле ID ?
просто уникальный идентификатор записи
 

alpine

Новичок
если первые 2 ответа - да, то GROUP BY USER_ID + MIN(PERIOD_START) MAX(PERIOD_END)
 

Фанат

oncle terrible
Команда форума
alpine
самый тупой вопросник, какой бывал в этом форуме.
ответы на все три вопроса очевидны и прописаны в вопросе.

4you
проще получить эти три строки в скрипте.
Хотя, конечно, при постраничном выводе будут проблемы.
 

alpine

Новичок
Фанат
Твое мнение я не спрашивал.

-~{}~ 16.03.07 11:39:

Кстати, по-моему поле ID нигде не используется или я не прав?
 

4you

еееххххх....
Автор оригинала: Фанат
alpine
самый тупой вопросник, какой бывал в этом форуме.
ответы на все три вопроса очевидны и прописаны в вопросе.

4you
проще получить эти три строки в скрипте.
Хотя, конечно, при постраничном выводе будут проблемы.
Да согласен, но постольку поскольку могу не знать каких аспектов в MySQL решил поинтересоваться. Поиск по сайту MySQL не подсказал ничего.

-~{}~ 16.03.07 11:42:

Автор оригинала: alpine
Фанат
Твое мнение я не спрашивал.

-~{}~ 16.03.07 11:39:

Кстати, по-моему поле ID нигде не используется или я не прав?
Для данного примера да
 

Фанат

oncle terrible
Команда форума
поиск по сайту врядли подскажет что-то.
сайт - это справоник синтаксиса.
а у тебя вопрос в алгоритме. Здесь нужен учебник, скорее.

как-то, может быть, можно группировать по условию PERIOD_START = PERIOD_END, но дальше мысль останавливается
 

4you

еееххххх....
Автор оригинала: Фанат
поиск по сайту врядли подскажет что-то.
сайт - это справоник синтаксиса.
а у тебя вопрос в алгоритме. Здесь нужен учебник, скорее.

как-то, может быть, можно группировать по условию PERIOD_START = PERIOD_END, но дальше мысль останавливается
вот примерно таже петрушка... ок будем думать.. может кто еще подскажет дельную мысль
 

akd

dive now, work later
Команда форума
имхо, одни запросом никак.

я бы думал в сторону временных таблиц и цикла по курсору.
 

alpine

Новичок
одним запросом не знаю как ... мысли такие ... в sql скрипте:

- упорядочить данные по началу интервала
- ввести переменную пользователя - счетчик
- ввести переменную пользователя окончание предыдущего интервала
- сравнивать конец предыдущего интервала с началом следующего интервала
- если разница между началом и окончанием периода == 1 день(как в примере данных выше) от начала след периода отнимаем один день
- если совпадает не увеличиваем счетчик
- если несовпадает увеличиваем
- группируем по значению счетчика
 

chira

Новичок
4you
с моими данными вот так получилось:
Код:
mysql> select * from d;
+----+---------+------------+------------+
| id | user_id | d1         | d2         |
+----+---------+------------+------------+
|  1 |       1 | 2007-01-15 | 2007-01-30 |
|  2 |       2 | 2007-01-10 | 2007-01-22 |
|  3 |       2 | 2007-01-23 | 2007-02-10 |
|  4 |       3 | 2007-01-01 | 2007-02-20 |
|  5 |       3 | 2007-02-21 | 2007-02-28 |
|  6 |       3 | 2007-03-01 | 2007-03-12 |
|  7 |       3 | 2007-03-13 | 2007-03-22 |
|  8 |       4 | 2007-03-13 | 2007-03-22 |
|  9 |       4 | 2007-01-15 | 2007-01-30 |
| 10 |       3 | 2007-03-25 | 2007-03-28 |
| 11 |       3 | 2006-01-15 | 2006-01-30 |
+----+---------+------------+------------+
11 rows in set (0.00 sec)

mysql> SELECT d.user_id, MIN(d.d1) d1, MAX(IFNULL(dd.d2,d.d2)) d2
    -> FROM d
    ->   LEFT JOIN d dd on d.user_id=dd.user_id AND ((d.d2 + INTERVAL 1 DAY) = dd.d1 OR (d.d1 - INTERVAL 1 DAY) = dd.d2)
    -> GROUP BY d.user_id, IFNULL(((d.d2 + INTERVAL 1 DAY) = dd.d1 OR (d.d1 - INTERVAL 1 DAY) = dd.d2),d.id+1)
    -> ;
+---------+------------+------------+
| user_id | d1         | d2         |
+---------+------------+------------+
|       1 | 2007-01-15 | 2007-01-30 |
|       2 | 2007-01-10 | 2007-02-10 |
|       3 | 2007-01-01 | 2007-03-22 |
|       3 | 2007-03-25 | 2007-03-28 |
|       3 | 2006-01-15 | 2006-01-30 |
|       4 | 2007-03-13 | 2007-03-22 |
|       4 | 2007-01-15 | 2007-01-30 |
+---------+------------+------------+
7 rows in set (0.00 sec)

mysql>
 

4you

еееххххх....
Автор оригинала: chira
4you
с моими данными вот так получилось:
Код:
mysql> select * from d;
+----+---------+------------+------------+
| id | user_id | d1         | d2         |
+----+---------+------------+------------+
|  1 |       1 | 2007-01-15 | 2007-01-30 |
|  2 |       2 | 2007-01-10 | 2007-01-22 |
|  3 |       2 | 2007-01-23 | 2007-02-10 |
|  4 |       3 | 2007-01-01 | 2007-02-20 |
|  5 |       3 | 2007-02-21 | 2007-02-28 |
|  6 |       3 | 2007-03-01 | 2007-03-12 |
|  7 |       3 | 2007-03-13 | 2007-03-22 |
|  8 |       4 | 2007-03-13 | 2007-03-22 |
|  9 |       4 | 2007-01-15 | 2007-01-30 |
| 10 |       3 | 2007-03-25 | 2007-03-28 |
| 11 |       3 | 2006-01-15 | 2006-01-30 |
+----+---------+------------+------------+
11 rows in set (0.00 sec)

mysql> SELECT d.user_id, MIN(d.d1) d1, MAX(IFNULL(dd.d2,d.d2)) d2
    -> FROM d
    ->   LEFT JOIN d dd on d.user_id=dd.user_id AND ((d.d2 + INTERVAL 1 DAY) = dd.d1 OR (d.d1 - INTERVAL 1 DAY) = dd.d2)
    -> GROUP BY d.user_id, IFNULL(((d.d2 + INTERVAL 1 DAY) = dd.d1 OR (d.d1 - INTERVAL 1 DAY) = dd.d2),d.id+1)
    -> ;
+---------+------------+------------+
| user_id | d1         | d2         |
+---------+------------+------------+
|       1 | 2007-01-15 | 2007-01-30 |
|       2 | 2007-01-10 | 2007-02-10 |
|       3 | 2007-01-01 | 2007-03-22 |
|       3 | 2007-03-25 | 2007-03-28 |
|       3 | 2006-01-15 | 2006-01-30 |
|       4 | 2007-03-13 | 2007-03-22 |
|       4 | 2007-01-15 | 2007-01-30 |
+---------+------------+------------+
7 rows in set (0.00 sec)

mysql>
Выглядит супер. Буду пробовать на своих данных. Спасибо
 
Сверху