Помогите в создании запроса

  • Автор темы Автор темы skytskyi
  • Дата начала Дата начала

skytskyi

Новичок
Помогите в создании запроса

Есть таблица Tabl с полями id-номер записи, Start- начало промежутка, End - конец промежутка на числовой оси. Нужно создать запрос, который должен выводить объединение значений отрезков на числовой осе. Например, если у меня задана таблица со значениями:

id |Start |End
01| 5 | 7
02| 10 | 100
03| 90 | 180
04| 200 | 300
05| 220 | 240
06| 260 | 280

То в результате выполнения запроса у меня должна получится следующая таблица

|Start |End
| 5 | 7
| 10 | 180
| 200 | 300
Буду очень признателен за помощь. Спасибо.
 
не понятно по какому признаку должно происходить объединение
 
Объединение должно происходить по следующему признаку, если промежуток входит в какой та другой больший, от первого, то ми оставляем, этот который есть больший, то есть если у нас есть два промежутка например начало 200, конец 300, і другой с началом в 220 і концом в 240, то ми оставляем первый, поскольку второй входит в него. Если у нас два промежутки с началом в 10 і 100 і второй с началом в 90 і концом в 180, то ми их объединяем. Ну а если у нас два промежутки с началом в 5 и концом в 7 і промежуток с началом в 10 и концом в 100, то ми их так и оставляем.
 
alpes
объединение должно происходить по признаку пересечения интервалов [Start, End].

skytskyi
имхо одним запросом не получится.
 
это я знаю, а как именно нужно оформить запрос, а то я даже не знаю с чего начать
 
Код:
mysql> SELECT * FROM `t`;
+----+-------+------+
| id | start | end  |
+----+-------+------+
|  1 |     5 |    7 |
|  2 |    10 |  100 |
|  3 |    90 |  180 |
|  4 |   200 |  300 |
|  5 |   220 |  240 |
|  6 |   260 |  280 |
+----+-------+------+
6 rows in set (0.00 sec)


mysql> DROP TABLE IF EXISTS `temporary`;
Query OK, 0 rows affected (0.01 sec)

mysql> CREATE  TABLE `temporary` SELECT DISTINCT `t1`.`start`, IF(`t2`.`end` > `
t1`.`end`, `t2`.`end`, `t1`.`end`) AS `end` FROM `t` `t1` LEFT JOIN `t` `t2` ON
`t2`.`start` > `t1`.`start` AND `t2`.`start` < `t1`.`end` ORDER BY `t1`.`start`;

Query OK, 6 rows affected (0.03 sec)
Records: 6  Duplicates: 0  Warnings: 0

mysql> SELECT `t3`.`start`, `t3`.`end`, COUNT(*) AS `cnt` FROM `temporary` `t3`
LEFT JOIN `temporary` `t4` ON `t3`.`start` >= `t4`.`start` AND `t3`.`end` <= `t4
`.`end` GROUP BY `t3`.`start`, `t3`.end HAVING `cnt` = 1;
+-------+------+-----+
| start | end  | cnt |
+-------+------+-----+
|     5 |    7 |   1 |
|    10 |  180 |   1 |
|   200 |  300 |   1 |
+-------+------+-----+
3 rows in set (0.01 sec)

ps: можно сделать таблицу TEMPORARY конечно же
 
без темпорари
Код:
SELECT DISTINCT MIN(LEAST(b1.start,IFNULL(b2.start,b1.start))) start, MAX(GREATEST(b1.end,IFNULL(b2.end,b1.end))) end
FROM b b1
	LEFT JOIN b b2 ON b1.start <= b2.end and b1.end >= b2.start and b1.id > b2.id
GROUP BY IFNULL(b2.start,b1.start),IFNULL(b2.end,b1.end);
 
chira
респект

ps:
Код:
MIN(LEAST(b1.start,b2.start)) start, MAX(GREATEST(b1.end,b2.end))
 
в таком варианте некоторые значения могут выпасть ...
Код:
mysql> select greatest(1000,null);
+------------------+
| greatest(1000,null) |
+------------------+
|             NULL |
+------------------+
1 row in set (0.01 sec)
 
pps: да и
and b1.id > b2.id
вроде тоже можно убрать..

-~{}~ 07.05.06 02:14:

Код:
mysql> select greatest(1,null);
+------------------+
| greatest(1,null) |
+------------------+
|                1 |
+------------------+
1 row in set (0.00 sec)

mysql> select version();
+------------+
| version()  |
+------------+
| 4.1.14-log |
+------------+
1 row in set (0.00 sec)
 
Код:
mysql> select greatest(1,null);
+------------------+
| greatest(1,null) |
+------------------+
|             NULL |
+------------------+
1 row in set (0.24 sec)

mysql> select version();
+---------------------+
| version()           |
+---------------------+
| 5.0.21-community-nt |
+---------------------+
1 row in set (0.01 sec)
 
если таблица не большая, то сойдёт и такой вариант
Код:
SELECT DISTINCT MIN(LEAST(b1.start,b2.start)) start, MAX(GREATEST(b1.end,b2.end)) end
FROM b b1
	INNER JOIN b b2 ON b1.start <= b2.end and b1.end >= b2.start
GROUP BY b2.start,b2.end;
 
с NULL в разных версиях MySQL работает по разному.
в пятой более правильно (по ссылке от zerkms)
если одно из значений в списке NULL, то общий результат неопределён, т.е. тоже NULL
 
хм.... тем не менее мне например логичнее что 1 > NULL

-~{}~ 07.05.06 02:32:

с другой стороны - тогда получается неопределённость -1 ? NULL ;)))
 
chira
я понимаю..... именно поэтому я и указал на -1 ? NULL, тем самым соглашаясь, что всё в версии 5.0.13+ сделано "правильнее" с точки зрения логики
 
Сверху