Rin
*
задача определения существования страницы по ее пути
Есть задача, которую можно решить несколькими способами.
Хотелось бы взглянуть на другие изящные альтернативные решения, работающие в MySQL 4.0.x
Предположим, что есть таблица для хранения древообразной структуры страниц (Nested Sets).
Пользователь заходит на страницу http://domain.com/company/history/
Через mod_rewrite мы можем получить путь страницы "/company/history/" в переменную, например, $page.
Нужно проверить, что страница "/company/history/" существует и получить ее заголовок (поле `caption` таблицы `page`).
[sql]
#
# Table structure for table page
#
CREATE TABLE `page` (
`id` int(10) unsigned NOT NULL auto_increment,
`ns_left` int(10) unsigned NOT NULL default '0',
`ns_right` int(10) unsigned NOT NULL default '0',
`ns_level` tinyint(3) unsigned NOT NULL default '0',
`name` varchar(255) NOT NULL default '',
`caption` varchar(255) NOT NULL default '',
PRIMARY KEY (`id`),
KEY `ns_level` (`ns_level`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
#
# Dumping data for table page
#
INSERT INTO `page` VALUES (1,1,12,0,'','');
INSERT INTO `page` VALUES (2,2,11,1,'/','Заглавная страница');
INSERT INTO `page` VALUES (3,3,4,2,'news/','Новости');
INSERT INTO `page` VALUES (4,5,8,2,'company/','Компания');
INSERT INTO `page` VALUES (5,9,10,2,'catalog/','Каталог продукции');
INSERT INTO `page` VALUES (6,6,7,3,'history/','История');
-- Вариант 1 для MySQL 4.1.x (связанные подзапросы)
-- EXPLAIN
SELECT t3.*
FROM page AS t3
WHERE d3.name = 'history/' AND t3.ns_level = 3
AND EXISTS ( SELECT 1
FROM page AS t2
WHERE t2.name = 'company/' AND t2.ns_level = 2
AND t2.ns_left < t3.ns_left
AND t2.ns_right > t3.ns_right
AND EXISTS ( SELECT 1
FROM page AS t1
WHERE t1.name = '/' AND t1.ns_level = 1
AND t1.ns_left < t2.ns_left
AND t1.ns_right > t2.ns_right ) )
-- Вариант 2 для MySQL 4.0.x (используя UNION):
-- EXPLAIN
(SELECT @ns_left := t.ns_left AS ns_left,
@ns_right := t.ns_right AS ns_right,
t.*
FROM page AS t
WHERE t.name = '/' AND t.ns_level = 1
LIMIT 1)
UNION ALL
(SELECT @ns_left := t.ns_left AS ns_left,
@ns_right := t.ns_right AS ns_right,
t.*
FROM page AS t
WHERE t.name = 'company/' AND t.ns_level = 2
AND t.ns_left > @ns_left
AND t.ns_right < @ns_right
LIMIT 1)
UNION ALL
(SELECT @ns_left := t.ns_left AS ns_left,
@ns_right := t.ns_right AS ns_right,
t.*
FROM page AS t
WHERE t.name = 'history/' AND t.ns_level = 3
AND t.ns_left > @ns_left
AND t.ns_right < @ns_right
LIMIT 1)
[/sql]
-~{}~ 22.04.06 00:37:
Второй вариант должен работать быстрее, т.к. узлы ищутся от корня к листам.
Есть задача, которую можно решить несколькими способами.
Хотелось бы взглянуть на другие изящные альтернативные решения, работающие в MySQL 4.0.x
Предположим, что есть таблица для хранения древообразной структуры страниц (Nested Sets).
Пользователь заходит на страницу http://domain.com/company/history/
Через mod_rewrite мы можем получить путь страницы "/company/history/" в переменную, например, $page.
Нужно проверить, что страница "/company/history/" существует и получить ее заголовок (поле `caption` таблицы `page`).
[sql]
#
# Table structure for table page
#
CREATE TABLE `page` (
`id` int(10) unsigned NOT NULL auto_increment,
`ns_left` int(10) unsigned NOT NULL default '0',
`ns_right` int(10) unsigned NOT NULL default '0',
`ns_level` tinyint(3) unsigned NOT NULL default '0',
`name` varchar(255) NOT NULL default '',
`caption` varchar(255) NOT NULL default '',
PRIMARY KEY (`id`),
KEY `ns_level` (`ns_level`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
#
# Dumping data for table page
#
INSERT INTO `page` VALUES (1,1,12,0,'','');
INSERT INTO `page` VALUES (2,2,11,1,'/','Заглавная страница');
INSERT INTO `page` VALUES (3,3,4,2,'news/','Новости');
INSERT INTO `page` VALUES (4,5,8,2,'company/','Компания');
INSERT INTO `page` VALUES (5,9,10,2,'catalog/','Каталог продукции');
INSERT INTO `page` VALUES (6,6,7,3,'history/','История');
-- Вариант 1 для MySQL 4.1.x (связанные подзапросы)
-- EXPLAIN
SELECT t3.*
FROM page AS t3
WHERE d3.name = 'history/' AND t3.ns_level = 3
AND EXISTS ( SELECT 1
FROM page AS t2
WHERE t2.name = 'company/' AND t2.ns_level = 2
AND t2.ns_left < t3.ns_left
AND t2.ns_right > t3.ns_right
AND EXISTS ( SELECT 1
FROM page AS t1
WHERE t1.name = '/' AND t1.ns_level = 1
AND t1.ns_left < t2.ns_left
AND t1.ns_right > t2.ns_right ) )
-- Вариант 2 для MySQL 4.0.x (используя UNION):
-- EXPLAIN
(SELECT @ns_left := t.ns_left AS ns_left,
@ns_right := t.ns_right AS ns_right,
t.*
FROM page AS t
WHERE t.name = '/' AND t.ns_level = 1
LIMIT 1)
UNION ALL
(SELECT @ns_left := t.ns_left AS ns_left,
@ns_right := t.ns_right AS ns_right,
t.*
FROM page AS t
WHERE t.name = 'company/' AND t.ns_level = 2
AND t.ns_left > @ns_left
AND t.ns_right < @ns_right
LIMIT 1)
UNION ALL
(SELECT @ns_left := t.ns_left AS ns_left,
@ns_right := t.ns_right AS ns_right,
t.*
FROM page AS t
WHERE t.name = 'history/' AND t.ns_level = 3
AND t.ns_left > @ns_left
AND t.ns_right < @ns_right
LIMIT 1)
[/sql]
-~{}~ 22.04.06 00:37:
Второй вариант должен работать быстрее, т.к. узлы ищутся от корня к листам.