假设您有一个存储有序树层次结构的平面表:
Id Name ParentId Order
1 'Node 1' 0 10
2 'Node 1.1' 1 10
3 'Node 2' 0 20
4 'Node 1.1.1' 2 10
5 'Node 2.1' 3 10
6 'Node 1.2' 1 20
Run Code Online (Sandbox Code Playgroud)
这是我们所拥有的图表[id] Name.根节点0是虚构的.
[0] ROOT
/ \
[1] Node 1 [3] Node 2
/ \ \
[2] Node 1.1 [6] Node 1.2 [5] Node 2.1
/
[4] Node 1.1.1
您将使用什么简约方法将其输出为HTML(或文本,就此而言)作为正确排序,正确缩进的树?
进一步假设你只有基本的数据结构(数组和散列图),没有带有父/子引用的花哨对象,没有ORM,没有框架,只有你的双手.该表表示为结果集,可以随机访问.
伪代码或普通英语是可以的,这纯粹是一个概念性的问题.
额外问题:在RDBMS中存储这样的树结构是否有根本更好的方法?
编辑和补充
回答一个评论者(Mark Bessey的)问题:根节点不是必需的,因为它永远不会被显示.ParentId = 0是表示"这些是顶级"的惯例.Order列定义了如何对具有相同父节点的节点进行排序.
我所谈到的"结果集"可以被描绘成一组哈希图(保留在该术语中).因为我的例子意味着已经存在.有些答案会加倍努力并首先构建它,但那没关系.
树可以任意深.每个节点可以有N个子节点.不过,我并没有考虑到"数百万条目".
不要将我选择的节点命名('Node 1.1.1')误认为是依赖的东西.节点同样可以称为"Frank"或"Bob",不暗示命名结构,这只是为了使其可读. …
我有这样的结构:
<Unit>
<SubUnit1>
<SubSubUnit1/>
<SubSubUnit2/>
...
<SubSubUnitN/>
</SubUnit1/>
<SubUnit2>
<SubSubUnit1/>
<SubSubUnit2/>
...
<SubSubUnitN/>
</SubUnit2/>
...
<SubUnitN>
<SubSubUnit1/>
<SubSubUnit2/>
...
<SubSubUnitN/>
</SubUnitN/>
</Unit>
Run Code Online (Sandbox Code Playgroud)
这个结构有3个级别:主单元,SubUnits和SubSubUnits.
我想通过UnitId选择所有孩子.
如果我按单位搜索,我必须得到所有树.
如果我通过SubUnit1搜索,我必须获得SubUnit1和SubUnit1的所有子项.
如果我搜索SubSubUnit2,我必须得到自己.
这是我的尝试:
with a(id, parentid, name)
as (
select id, parentId, name
from customer a
where parentId is null
union all
select a.id, a.parentid, a.Name
from customer
inner join a on customer.parentId = customer.id
)
select parentid, id, name
from customer pod
where pod.parentid in (
select id
from customer grbs
where grbs.parentid in …Run Code Online (Sandbox Code Playgroud) 我正在制作一个视频网站,其中的类别将被嵌套:
例如编程 - > C语言 - > MIT视频 - >视频1编程 - > C语言 - >斯坦福视频 - >视频1编程 - > Python - >视频1
这些类别和子类别将由用户即时创建.当人们以可导航菜单的形式创建它们时,我将需要显示它们,以便人们可以轻松浏览该集合.
有人可以帮助我如何创建这样的数据库吗?
给出一个简单的(id,description)表t1,例如
id description
-- -----------
1 Alice
2 Bob
3 Carol
4 David
5 Erica
6 Fred
Run Code Online (Sandbox Code Playgroud)
和父子关系表t2,如
parent child
------ -----
1 2
1 3
4 5
5 6
Run Code Online (Sandbox Code Playgroud)
Oracle提供了一种将此方法作为具有一些自定义语法扩展的树遍历的方法:
select parent, child, sys_connect_by_path(child, '/') as "path"
from t2
connect by prior parent = child
Run Code Online (Sandbox Code Playgroud)
确切的语法并不重要,我可能在上面做了一个错误.重要的是上面会产生一些看起来像的东西
parent child path
------ ----- ----
1 2 /1/2
1 3 /1/3
4 5 /4/5
4 6 /4/5/6
5 6 /5/6
Run Code Online (Sandbox Code Playgroud)
我的问题是:是否可以在sys_connect_by_path()中连接另一个表,例如上面的t1表,以生成类似于:
parent child path
------ ----- ----
1 2 /Alice/Bob
1 3 …Run Code Online (Sandbox Code Playgroud) 我需要在用户树所获得的每个级别上加分.级别1是用户1级以下用户的用户点数之和.2级是用户等级2级以下的1级点...
计算在非生产服务器上每月发生一次,不用担心性能问题.
SQL会是什么样子的呢?
如果你感到困惑,别担心,我也好!
用户表:
ID ParentID Points
1 0 230
2 1 150
3 0 80
4 1 110
5 4 54
6 4 342
Tree:
0
|---\
1 3
| \
2 4---
\ \
5 6
Run Code Online (Sandbox Code Playgroud)
输出应该是:
ID Points Level1 Level2
1 230 150+110 150+110+54+342
2 150
3 80
4 110 54+342
5 54
6 342
Run Code Online (Sandbox Code Playgroud)
SQL Server语法和函数最好......
我有四张桌子
create table entities{
integer id;
string name;
}
create table users{
integer id;//fk to entities
string email;
}
create table groups{
integer id;//fk to entities
}
create table group_members{
integer group_id; //fk to group
integer entity_id;//fk to entity
}
Run Code Online (Sandbox Code Playgroud)
我想创建一个查询,直接或间接返回用户所属的所有组.显而易见的解决方案是在应用程序级别进行递归.我想知道我可以对我的数据模型进行哪些更改以减少数据库访问,从而获得更好的性能.
我正在我的应用程序中构建一个嵌套的评论回复系统.
一切当前按预期工作,但我发现自己必须使用几个MySQL查询才能检索所需的数据.更糟糕的是,对'回复'的查询是在foreach循环中.这意味着虽然它现在表现令人钦佩,但它远非最佳,并且随着数据集的增长会引起问题.
因此,我希望在进一步深入发展之前解决这个问题.
由于该应用程序的表与该网站的wordpress博客共享相同,因此我使用wordpress简写进行查询.
生成页面的当前方式如下:
查询评论表并检索与项目相关的所有结果: -
$commentquery = "select projects_comments.*, users.user_url, users.display_name
from ".$wpdb->prefix."projects_comments projects_comments
left join ".$wpdb->prefix."users users on users.ID=projects_comments.userid
where projectid = '$projectid'
order by projects_comments.commentid desc
";
$comments = $wpdb->get_results($commentquery);
Run Code Online (Sandbox Code Playgroud)
然后我执行foreach循环如下: -
if($comments) {
foreach ( $comments as $c )
{
$replyquery = "select project_replies.*, users.user_url, users.display_name
from ".$wpdb->prefix."project_replies project_replies
left join ".$wpdb->prefix."users users on users.ID=project_replies.uid
where project_replies.cid = '$c->commentid'
order by project_replies.id desc
limit 2
";
$replies = $wpdb->get_results($replyquery);
asort($replies);
$countquery = "select count(*)
from …Run Code Online (Sandbox Code Playgroud) 我有一个菜单系统表,具有以下结构和一些数据.
ID, Text, ParentID, DestinationID 1, Applications, (null), (null) 2, Games, (null), (null) 3, Office, 1, (null) 4, Text Editing, 1, (null) 5, Media, (null), (null) 6, Word, 3, 1 7, Excel, 3, 2 8, Crysis, 2, 3
我需要的是一个查询,我可以传递菜单ID,它将返回一个具有该ID作为子项的项目列表.但是,我需要它才能返回具有到目的地的有效路径的孩子.因此,在上面的示例中,用户将首先显示(应用程序,游戏),当他选择应用程序时,他将被呈现(Office).应省略文本编辑和媒体,因为它们下面没有有效的目的地.
最棘手的是,任何给定的菜单都没有预定的深度.
编辑:
今天,问题出现在MS SQL 2008上,但在过去两周内,我需要针对SQLite和SQL CE的类似解决方案.理想的解决方案不应该绑定到任何特定的SQL引擎.
天真的方法是将整个路径作为字符串放入数据库中,这适用于玩具数据库。然而,这种方法有一些缺陷。例如,假设我在 /var/www/sites/ 下有 100K 个文件,那么在数据库中存储 /var/www/sites 100K 次是非常低效的。我确信有更好的方法来做到这一点。
我只想对 DVD 上的文件路径建立索引,然后搜索 mp3 文件或目录等。首选的 RDBMS 是 SQLite(也许是 FTS Tables?)。我的目标是学习,我知道有很多桌面搜索引擎可以实现这一点。
sql ×6
tree ×4
mysql ×2
recursion ×2
algorithm ×1
categories ×1
connect-by ×1
database ×1
nested ×1
oracle ×1
php ×1
postgresql ×1
sql-server ×1
sqlite ×1