嵌套的SELECT + INNER JOIN

时间:2014-10-06 17:34:43

标签: mysql nested normalization

第一张表

  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
以色列
- 阿什杜德

所以,我的查询是

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]?

1 个答案:

答案 0 :(得分: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