Найти первую свободную область через запрос MySQL
Формулировка задачи:
Приложил картинку: в базе хранятся закрашенные области (серый цвет), как координаты левого верхнего угла и правого нижнего, т.е. ЧЕТЫРЕ числа (х1,у1,х2,у2). Как запросом в базу MySql получить координаты свободной области, если условия такие:
п.1 начиная сверху слева найти свободную область размером 1х1
п.2 начиная сверху слева найти свободную область размером 2х2
То есть для п.1 ответ должен быть 0,0,1,1 (голубой квадратик) для п.2 = 6,0,8,2 (оранжевый квадратик)
Сэмпл базы:
Листинг программы
- CREATE TABLE `items` (
- `id` INT(11) NOT NULL,
- `x1` SMALLINT(4) NOT NULL,
- `y1` SMALLINT(4) NOT NULL,
- `x2` SMALLINT(4) NOT NULL,
- `y2` SMALLINT(4) NOT NULL
- ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
- INSERT INTO `items` (`id`, `x1`, `y1`, `x2`, `y2`) VALUES
- (1, 3, 0, 6, 4),
- (2, 8, 0, 9, 2),
- (3, 0, 1, 2, 2),
- (4, 0, 3, 2, 5),
- (5, 7, 3, 9, 7),
- (6, 1, 6, 6, 7),
- (7, 1, 8, 2, 10);
Решение задачи: «Найти первую свободную область через запрос MySQL»
textual
Листинг программы
- CREATE TABLE items (
- id INT UNSIGNED NOT NULL AUTO_INCREMENT,
- t SMALLINT NOT NULL,
- l SMALLINT NOT NULL,
- b SMALLINT NOT NULL,
- r SMALLINT NOT NULL,
- ls linestring NOT NULL,
- CONSTRAINT pk_items_id PRIMARY KEY(id),
- spatial INDEX (ls)
- ) engine = myisam DEFAULT CHARACTER SET = cp1251;
- delimiter ~
- CREATE definer = CURRENT_USER TRIGGER bi_items BEFORE INSERT ON items
- FOR each ROW
- BEGIN
- SET NEW.ls = linestring(point(NEW.t, NEW.l), point(NEW.b, NEW.r));
- END~
- CREATE definer = CURRENT_USER FUNCTION getCell (
- asize INT, -- размер квадратика
- maxsize INT) -- размер проверяемой квадратной (обязательно!) матрицы [0, 1, ..., maxsize]
- RETURNS linestring
- BEGIN
- DECLARE nR INT DEFAULT 0; -- row
- DECLARE nC INT DEFAULT 0; -- col
- DECLARE find tinyint DEFAULT 1;
- X: repeat
- SELECT
- SUM(intersects(linestring(point(nR + 0.1, nC + 0.1), point(nR + asize - 0.1, nC + asize - 0.1)), ls))
- INTO find
- FROM items;
- IF find > 0 THEN
- IF (nC + asize + 1) > maxsize THEN
- SET nC = 0;
- IF (nR + asize + 1) > maxsize THEN
- leave X;
- ELSE
- SET nR = nR + 1;
- END IF;
- ELSE
- SET nC = nC + 1;
- END IF;
- END IF;
- until find = 0
- END repeat;
- IF find = 0 THEN
- RETURN linestring(point(nR, nC), point(nR + asize, nC + asize));
- ELSE
- RETURN NULL;
- END IF;
- END~
- delimiter ;
- INSERT INTO items(t, l, b, r) VALUES
- (0, 3, 4, 6),
- (0, 8, 2, 9),
- (1, 0, 2, 2),
- (3, 0, 5, 2),
- (3, 7, 7, 9),
- (6, 1, 7, 6),
- (8, 1, 10,2);
- SELECT astext(getCell(1, 10)) FROM dual; -- поиск ячейки размером 1x1
- SELECT astext(getCell(2, 10)) FROM dual; -- поиск ячейки размером 2x2
Объяснение кода листинга программы
- Создание таблицы
items
с полямиid
,t
,l
,b
,r
,ls
типаINT
,SMALLINT
,SMALLINT
,SMALLINT
,SMALLINT
,linestring
соответственно. Типlinestring
используется для хранения геометрических данных. - Создание триггера
bi_items
перед таблицейitems
, который будет автоматически присваивать геометрическое значение в полеls
при вставке новой записи. - Создание функции
getCell
, которая принимает два параметра:asize
иmaxsize
. Функция проверяет пересечение вставленной в таблицуitems
линии с каждой ячейкой размеромasize x maxsize
и возвращает координаты первой свободной ячейки. - Вставка данных в таблицу
items
. - Вызов функции
getCell
с размерами1x1
и2x2
для поиска свободных ячеек.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д