【发布时间】:2010-08-03 16:48:44
【问题描述】:
我目前有一个包含自联接的查询,用于从使用nested sets model 存储公司组织信息的表中查询员工的所有直接和间接经理。在此 SQL 表示法中,以冒号开头的数字(例如 :1)是变量:
select parent.empid, parent.depth from RelationshipMgr as node join
RelationshipMgr as parent on node.lft between parent.lft and parent.rgt
and node.empid = :1 order by parent.lft
通过将parent.depth = node.depth - :2 添加到联接条件或 where 子句中,我可以轻松地仅返回员工上方 n 级的经理的 ID(附带问题:哪个更快?)。
问题:我正在尝试将此查询转换为视图,但运气不佳。问题是我的大部分或所有变量都在我的查询的连接条件中。我目前最好的计划是将这些部分分成列,然后我可以在查询视图时使用 where 子句,例如:
select node.EmpID, parent.empid as MgrID, parent.depth as MgrDepth,
node.depth - parent.depth as MgrRelativeAltitude from RelationshipMgr as node
join RelationshipMgr as parent on node.lft between parent.lft and parent.rgt
您可以看到我必须发明MgrRelativeAltitude 列才能找到比员工高n 级的经理的 ID,但这并不是最大的问题。我担心这会产生严重的性能问题,因为 SQL Server 似乎是按照连接条件指定的方式进行完全连接,然后通过 where 子句对其进行过滤,而不是智能地使用 where 子句来限制连接。 有没有更好的方法来创建视图?我是否应该将其保留为查询并忘记制作视图?通过将其设为存储过程而不是视图,我会有所收获吗?
请不要说“过早的优化是邪恶的”......这并不为时过早。我要替换的实现使用了诸如混蛋邻接列表之类的东西,该列表具有将员工与其直接和间接经理中的任何一个相关联的记录……最坏的情况是 O(n^2) 记录,并且可以预见地遇到严重的性能问题时我们在层级中有超过 300,000 名员工。我的新嵌套集实现将缓解这些性能问题,除了这个查询...如果您在建议的视图上执行select *,结果将与我尝试替换的旧表几乎相同,并且这让我非常担心。
【问题讨论】:
-
没有看到表格,我不确定数据的结构(不确定 LFT / Rgt 是什么。)如果您使用的是相对较新的 SQL Server;我会看看 CTE 来处理您的查询 - 您通常可以使复杂的东西更容易阅读。 MSSQL Tips 上的此页面使用了一个类似的示例,可能会有所帮助mssqltips.com/tip.asp?tip=1520
-
@u07ch 这是一个花园品种嵌套集模型......我的桌子结构真的没有什么特别之处。 “lft”和“rgt”是嵌套集技术的左右列(有时也分别称为向下和向上)。这些名称是相当标准的,因为“left”和“right”是 SQL 中的保留字。我在我的问题中提供了一个链接,但这是另一个(向下滚动到嵌套集部分):dev.mysql.com/tech-resources/articles/hierarchical-data.html
标签: sql sql-server query-optimization hierarchical-data nested-sets