2014-10-06 3 views
0

Первая таблицаВложенные SELECT + INNER JOIN

CREATE TABLE IF NOT EXISTS `city_node` (
`node_id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
`title` varchar(50) NOT NULL, 
`parent_node_id` int(10) unsigned NOT NULL DEFAULT '0', 
`lft` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Nested set info ''left'' value', 
`rgt` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Nested set info ''right'' value', 
`depth` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Depth = 0: no parent', 
PRIMARY KEY (`node_id`), 
KEY `parent_node_id` (`parent_node_id`), 
KEY `lft` (`lft`)) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=26; 

И данные

INSERT INTO `city_node` (`node_id`, `title`, `parent_node_id`, `lft`, `rgt`, `depth`) VALUES 
(1, 'Great Britain', 0, 1, 20, 0), 
(3, 'England', 1, 2, 9, 1), 
(7, 'Scotland', 1, 16, 19, 1), 
(8, 'Edinburgh', 7, 17, 18, 2), 
(9, 'Wales', 1, 10, 15, 1), 
(10, 'Cardiff', 9, 11, 12, 2), 
(11, 'London', 3, 3, 4, 2), 
(12, 'Birmingham', 3, 5, 6, 2), 
(13, 'Germany', 0, 21, 26, 0), 
(14, 'Stuttgart', 13, 22, 23, 1), 
(15, 'Newport', 9, 13, 14, 2), 
(16, 'Munich', 13, 24, 25, 1), 
(17, 'Israel', 0, 27, 32, 0), 
(18, 'Tel Aviv', 17, 28, 29, 1), 
(19, 'Ashdod', 17, 30, 31, 1), 
(20, 'USA', 0, 33, 38, 0), 
(21, 'New York', 20, 34, 35, 1), 
(24, 'Liverpool', 3, 7, 8, 2), 
(25, 'Detroit', 20, 36, 37, 1); 

Второй стол

CREATE TABLE IF NOT EXISTS `city_node_entity` (
    `node_id` int(10) NOT NULL, 
    `entity` tinyint(3) unsigned NOT NULL DEFAULT '1', 
    KEY `node_id` (`node_id`,`entity`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

И данные

INSERT INTO `city_node_entity` (`node_id`, `entity`) VALUES 
(11, 1), 
(12, 1), 
(16, 1), 
(19, 1); 

Я хочу получить узел с объектом 1 и его предков, как этот

Великобритании
--England
---- Лондон
---- Бирмингем
Германия
--Munich
Израиль
--Ashdod

Итак, мой запрос

SELECT DISTINCT(node_ext.node_id), node_ext.* 
FROM city_node_entity AS entity 
LEFT JOIN city_node AS node 
    ON entity.node_id = node.node_id 
LEFT JOIN city_node AS node_ext 
    ON node_ext.lft <= node.lft AND node_ext.rgt >= node.rgt 
WHERE entity.entity = 1 
ORDER BY node_ext.lft 

Но пояснения показывают -Используя где; Использование индекса; Использование временных; Использование filesort

Есть ли какие-либо другие запросы, чтобы получить тот же результат, но с меньшим [EXTRA]?

+0

MySQL не поддерживает рекурсивные запросы ... сколько уровней вложенности будет это идти? –

+0

Уровни глубины не имеют предела – kedoff

+0

, тогда это невозможно в mysql ... нет поддержки для рекурсивных запросов .. если я знаю, сколько уровней тогда можно, но только этим –

ответ

0

Единственное, что вы можете сделать для рекурсивных запросов, - запустить его с помощью объединений для каждого родителя/дочернего элемента .... потому что ваша вторая таблица является фактическим названием города, и вы хотите работать в обратном направлении, вы можете сделать это так. .. просто добавить больше присоединяется пока все результаты равны нулю, и вы будете иметь себе полное дерево

SELECT node.title AS child, t2.title as parent1, t3.title as parent2, t4.title as parent3 
FROM city_node_entity AS entity 
LEFT JOIN city_node AS node ON entity.node_id = node.node_id 
LEFT JOIN city_node AS t2 ON t2.node_id = node.parent_node_id 
LEFT JOIN city_node AS t3 ON t3.node_id = t2.parent_node_id 
LEFT JOIN city_node AS t4 ON t4.node_id = t3.parent_node_id; 

Fiddle Demo

+0

Разве это не подрывает точку работы с вложенными наборами? – Strawberry

+0

@Strawberry, учитывая, что MySQL не имеет рекурсивных функций, это лучшее, что вы можете сделать только в MySQL –

+0

Но я думал, что вложенные наборы должны были избавиться от необходимости рекурсии - возможно, я неправильно понял вопрос :-( – Strawberry