SQL树结构父子

时间:2015-02-25 02:04:57

标签: php mysql zend-framework recursion hierarchical-query

我有以下数据:

                id                  parent_id           
                ------------------  ------------------  
                Editor              null
                Printer             Editor
                TextWritingProggie  Printer
                LaTeX               TextWritingProggie
                OOfficeWriter       TextWritingProggie
                PhoneBook           TextWritingProggie

我正在查询PhoneBook id及其所有父母。它应该是一个层次结构,通向编辑器,因为他的父级为空,并且他通过打印机连接,打印机通过TextWritingProggie连接,然后连接到电话簿。

我认为使用SQL是更优选的,但可能需要通过PHP来处理。

这是我到目前为止所得到的,但它在不包含TextWritingProggie的记录后停止

SELECT * FROM acl_resources 
WHERE id = 'TextWritingProggie' OR parent_id = 'TextWritingProggie' 
ORDER BY COALESCE(parent_id, id), parent_id IS NOT NULL, id

任何帮助都会很棒

1 个答案:

答案 0 :(得分:0)

一些RDBMS产品提供内置的分层查询。例如,Oracle SQL has一个START WITH ... CONNECT BY语法,您可以使用此类查询来获取结果。

 SELECT id, SYS_CONNECT_BY_PATH(parent_id, '/'), LEVEL -- Oracle
   FROM res
  WHERE id='PhoneBook'
CONNECT BY prior id=parent_id
  ORDER BY LEVEL DESC

但不是MySQL。你必须以某种方式伪造它。一种方法是检索数据并在应用程序的内存中构建层次结构。

另一种方法是使用一系列LEFT JOIN操作,这些操作比预期的层次结构深度更长。这个查询有点难看,但它确实有效。这种查询的每一行都包含该行的“族谱”。以下是您的数据示例(http://sqlfiddle.com/#!2/bab1d/4/0):

select a.id a, b.id b, c.id c, d.id d, e.id e, f.id f, g.id g  /*MySQL*/
  from res a
  left join res b on a.parent_id = b.id
  left join res c on b.parent_id = c.id
  left join res d on c.parent_id = d.id
  left join res e on d.parent_id = e.id
  left join res f on e.parent_id = f.id
  left join res g on f.parent_id = g.id
where a.id = 'PhoneBook'

此特定查询的结果是

|         A |                  B |       C |      D |      E |      F |      G |
|-----------|--------------------|---------|--------|--------|--------|--------|
| PhoneBook | TextWritingProggie | Printer | Editor | (null) | (null) | (null) |

在Oracle层次结构查询中编码为CONNECT BY PRIOR id = parent_id的逻辑在此处显示为重复ON操作的重复LEFT JOIN子句。