选择类别属于层次结构中任何类别的产品
我有一个包含类别 FK 的产品表,类别表的创建方式使每个类别都可以有一个父类别,例如:
Computers
Processors
Intel
Pentium
Core 2 Duo
AMD
Athlon
我需要进行一个选择查询,如果所选类别是处理器,它将返回Intel、Pentium、Core 2 Duo、Amd 等产品...
我考虑创建某种“缓存”,它将存储数据库中每个类别的层次结构中的所有类别,并将“IN”包含在where 子句。 这是最好的解决方案吗?
I have a products table that contains a FK for a category, the Categories table is created in a way that each category can have a parent category, example:
Computers
Processors
Intel
Pentium
Core 2 Duo
AMD
Athlon
I need to make a select query that if the selected category is Processors, it will return products that is in Intel, Pentium, Core 2 Duo, Amd, etc...
I thought about creating some sort of "cache" that will store all the categories in the hierarchy for every category in the db and include the "IN" in the where clause. Is this the best solution?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
最好的解决方案是在数据库设计阶段。 您的类别表需要是一个嵌套集。 文章 管理 MySQL 中的分层数据 并不是 MySQL 特定的(尽管有标题),并且很好地概述了在数据库表中存储层次结构的不同方法。
执行摘要:
嵌套集
基于标准parent_id的层次结构
因此根据您的示例,如果您的层次结构表是嵌套的设置您的查询将如下所示:
2 和 11 分别是
Processors
记录的左侧和右侧。The best solution for this is at the database design stage. Your categories table needs to be a Nested Set. The article Managing Hierarchical Data in MySQL is not that MySQL specific (despite the title), and gives a great overview of the different methods of storing a hierarchy in a database table.
Executive Summary:
Nested Sets
Standard parent_id based hierarchy
So based on your example, if your hierarchy table was a nested set your query would look something like this:
the 2 and 11 are the left and right respectively of the
Processors
record.看起来像是公共表表达式的工作..大致如下:
应该选择名称为“处理器”的类别及其任何后代,应该能够在 IN 子句中使用它来拉回产品。
Looks like a job for a Common Table Expression.. something along the lines of:
That should select the category whose name is 'Processors' and any of it's descendents, should be able to use that in an IN clause to pull back the products.
我过去做过类似的事情,首先查询类别 id,然后查询“IN”这些类别的产品。 获取类别是困难的一点,您有几个选择:
如果您不想在应用程序端执行此操作,则存储过程可以提供帮助。
I have done similar things in the past, first querying for the category ids, then querying for the products "IN" those categories. Getting the categories is the hard bit, and you have a few options:
Stored procedures can help if you don't want to do this app-side.
你想要找到的是类别“父”关系的传递闭包。 我认为类别层次结构深度没有限制,因此您无法制定单个 SQL 查询来查找所有类别。 我要做的(以伪代码)是这样的:
所以继续查询子项,直到找不到更多子项。 这在速度方面表现良好,除非您有退化的层次结构(例如,1000 个类别,每个类别都是另一个类别的子类别)或大量的总类别。 在第二种情况下,您始终可以使用临时表来保持应用程序和数据库之间的数据传输较小。
What you want to find is the transitive closure of the category "parent" relation. I suppose there's no limitation to the category hierarchy depth, so you can't formulate a single SQL query which finds all categories. What I would do (in pseudocode) is this:
So just keep on querying for children until no more are found. This behaves well in terms of speed unless you have a degenerated hierarchy (say, 1000 categories, each a child of another), or a large number of total categories. In the second case, you could always work with temporary tables to keep data transfer between your app and the database small.
也许类似于:
[编辑]如果类别深度大于一,这将形成您最里面的查询。 我怀疑您可以设计一个存储过程,该存储过程将在表中向下钻取,直到内部查询返回的 id 没有子级为止——可能最好有一个属性将类别标记为层次结构中的终端节点——然后对这些 id 执行外部查询。
Maybe something like:
[EDIT] If the category depth is greater than one this would form your innermost query. I suspect that you could design a stored procedure that would drill down in the table until the ids returned by the inner query did not have children -- probably better to have an attribute that marks a category as a terminal node in the hierarchy -- then perform the outer query on those ids.
如果您像这样直接运行该示例的最后一部分,那么它实际上不起作用。 只需从产品中删除选择并用简单的 SELECT * FROM r 替换即可
The last part of the example isn't actually working if you're running it straight like this. Just remove the select from the products and substitute with a simple SELECT * FROM r
这应该从给定类别开始递归所有“子”类别。
This should recurse down all the 'child' catagories starting from a given catagory.
我喜欢使用堆栈临时表来存储分层数据。
这是一个粗略的示例 -
这里有一个很好的解释 链接文本
i like to use a stack temp table for hierarchal data.
here's a rough example -
there is a good explanation here link text
我几天前对另一个问题的回答适用于此... SQL 中的递归
我在书中链接了一些方法,它们应该可以很好地涵盖您的情况。
My answer to another question from a couple days ago applies here... recursion in SQL
There are some methods in the book which I've linked which should cover your situation nicely.