使用SQL在asp.net中创建分层菜单

时间:2014-03-04 15:13:05

标签: asp.net sql

我正在尝试使用asp.net中的SQL数据源创建分层菜单。我在订购桌面时遇到了麻烦,因此我可以轻松地在asp.net中创建菜单。如果有人有任何想法,可能有更好的方法来做到这一点......

我目前有一个看起来像这样的表(组成样本数据),根目录只有文件夹,只有文件夹可以有文件夹ID:

+-------------------+---------------------+-----------+-----------+
| Name_FolderorItem | Parent_Folder       | Id_Folder | Menuplace |
+-------------------+---------------------+-----------+-----------+
| c FOLDER          | ROOT                | c_FOLDER  | 1         |
| d FOLDER          | j_FOLDER            | d_FOLDER  | 2         |
| a FOLDER          | ROOT                | a_FOLDER  | 1         |
| j FOLDER          | ROOT                | j_FOLDER  | 1         |
| f FOLDER          | ROOT                | f_FOLDER  | 1         |
| r FOLDER          | f_FOLDER            | r_FOLDER  | 2         |
| i FOLDER          | d_FOLDER            | i_FOLDER  | 3         |
| a ITEM            | j_FOLDER            |           | 2         |
| d ITEM            | c_FOLDER            |           | 2         |
| z ITEM            | f_FOLDER            |           | 2         |
| r ITEM            | d_FOLDER            |           | 3         |
+-------------------+---------------------+-----------+-----------+

我在想,如果我命令它在第一级按字母顺序排列,则在每个更深层次上按字母顺序排列:

+-------------------+---------------------+-----------+-----------+
| Name_FolderorItem | Parent_Folder       | Id_Folder | Menuplace |
+-------------------+---------------------+-----------+-----------+
| a FOLDER          | ROOT                | a_FOLDER  | 1         |
| c FOLDER          | ROOT                | c_FOLDER  | 1         |
| d ITEM            | c_FOLDER            |           | 2         |
| f FOLDER          | ROOT                | f_FOLDER  | 1         |
| r FOLDER          | f_FOLDER            | r_FOLDER  | 2         |
| z ITEM            | f_FOLDER            |           | 2         |
| j FOLDER          | ROOT                | j_FOLDER  | 1         |
| a ITEM            | j_FOLDER            |           | 2         |
| d FOLDER          | j_FOLDER            | d_FOLDER  | 2         |
| i FOLDER          | d_FOLDER            | i_FOLDER  | 3         |
| r ITEM            | d_FOLDER            |           | 3         |
+-------------------+---------------------+-----------+-----------+

然后我可以使用listview来获取这个菜单结构:

a FOLDER
c FOLDER
- d ITEM
f FOLDER
- r FOLDER (r FOLDER is located in f folder)
- z ITEM
j FOLDER
- a item
- d FOLDER
- - i FOLDER
- - r ITEM

我似乎无法找出所需的SQL来获取文件夹,然后优先考虑其中的内容而不是该级别上的其他文件夹/项目。

如果你对允许这种排序的SQL语句有任何想法,我将不胜感激,提前谢谢

编辑: 这是我正在使用的查询,感谢您的帮助

SELECT *
FROM table
START WITH Parent_Folder LIKE 'ROOT'
CONNECT BY PRIOR Id_Folder LIKE Parent_folder;

1 个答案:

答案 0 :(得分:1)

这基本上是在数据库中存储 有序树 的问题。我过去曾尝试过一些方法,并会推荐这个方法:

-----------------------------------
| NodeID |   ParentID  |  Order   |
-----------------------------------
| 1      |       -1    |     1    |
| 2      |        1    |     1    |
| 3      |        1    |     2    |
| 4      |        3    |     1    |
-----------------------------------

GIST是每一行对应树中的一个节点(或您的案例中的菜单项),它有一个指向父节点的parentID。根节点要么为null,要么-1具有其parentID,因为它没有。现在,要获取直接位于根目录下的所有节点,您可以使用

SELECT * FROM table WHERE ParentID = -1 ORDER BY [Order]

[Order]告诉您如何直接在特定父节点下订购节点。 (好吧,使用SQL关键字命名列不太好,但暂时不要忘记)。所以在我的例子中你可以看到“2”和“3”都在根目录下,但“2”首先出现。要直接选择“3”下的节点(换句话说是其子节点),您可以使用

SELECT * FROM table WHERE ParentID = 3 ORDER BY [Order]

这种方法的优点是可以轻松查询菜单。缺点是更新时,必须确保共享相同ParentID的节点(换句话说,在同一父节点下)不共享名称[Order]。

替代方法

另一种方法是将树存储为链接列表:

-----------------------------------
|NodeID |  ParentID  | PrevID     | (optionally you can store NextID as well)
-----------------------------------
| 1     |  -1        | -1         |
| 2     |   1        | -1         |
| 3     |   1        | 2          |
| 4     |  3         | -1         |
-----------------------------------

如果您的树非常大并且需要快速浏览兄弟节点,这种方法可以提供更好的性能。