如何排除 SQL 树中匹配连接的行
更新:在尝试了几个小时后,采用了多查询解决方案,并使用仅包含父属性的表来确定哪些项目需要更新。
抱歉,标题不好,我不知道如何简洁地描述这个问题。
我有一组应与属性具有一对一关系的项目。
我有一个查询返回数据错误且这种关系已被破坏的那些行(一对多)。我正在收集这些行来修复它们并恢复这种一对一的关系。
这是我的实际问题的理论上的简化,但我将根据要求在此处发布示例表架构。
item
表:
+------------+------------+-----------+
| item_id | name | attr_id |
+------------+------------+-----------+
| 1 | BMW 320d | 20 |
| 1 | BMW 320d | 21 |
| 2 | BMW 335i | 23 |
| 2 | BMW 335i | 34 |
+------------+------------+-----------+
attribute
表:
+---------+-----------------+------------+
| attr_id | value | parent_id |
+---------+-----------------+------------+
| 20 | SE | 21 |
| 21 | M Sport | 0 |
| 23 | AC | 24 |
| 24 | Climate control | 0 |
....
| 34 | Leather seats | 0 |
+---------+-----------------+------------+
返回具有多个属性的项目的简单查询。
SELECT item_id, COUNT(DISTINCT(attr_id)) AS attributes
FROM item GROUP BY item_id HAVING attributes > 1
这给我一个像这样的结果集:
+-----------+------------+
| item_id | attributes |
+-----------+------------+
| 1 | 2 |
| 2 | 2 |
| 3 | 2 |
-- etc. --
但是,有一个例外。 attribute
表可以通过表中的父链接保存树结构。对于某些行,parent_id
可以保存另一个属性的 ID。这棵树只有一层。示例:
+---------+-----------------+------------+
| attr_id | value | parent_id |
+---------+-----------------+------------+
| 20 | SE | 21 |
| 21 | M Sport | 0 |
....
我不想想要检索原始查询中的项目,其中对于一对关联属性,它们像属性 20 和 20 一样相关。 21.
我确实想要检索项目,其中:
- 属性
- 对于两个或多个不相关的属性没有父级(例如属性 23 和 34)
所需的示例结果,只需项目 ID:
+------------+
| item_id |
+------------+
| 2 |
+------------+
如何我加入 items
中的 attributes
并排除这些行?
我是否使用临时表或者可以通过单个查询实现此目的?
谢谢。
Update: After playing around with this for a few hours, went with a multi-query solution and used a table that only contained parent attributes to determine which items needed updating.
Sorry for the poor title, I couldn't think how to concisely describe this problem.
I have a set of items that should have a 1-to-1 relationship with an attribute.
I have a query to return those rows where the data is wrong and this relationship has been broken (1-to-many). I'm gathering these rows to fix them and restore this 1-to-1 relationship.
This is a theoretical simplification of my actual problem but I'll post example table schema here as it was requested.
item
table:
+------------+------------+-----------+
| item_id | name | attr_id |
+------------+------------+-----------+
| 1 | BMW 320d | 20 |
| 1 | BMW 320d | 21 |
| 2 | BMW 335i | 23 |
| 2 | BMW 335i | 34 |
+------------+------------+-----------+
attribute
table:
+---------+-----------------+------------+
| attr_id | value | parent_id |
+---------+-----------------+------------+
| 20 | SE | 21 |
| 21 | M Sport | 0 |
| 23 | AC | 24 |
| 24 | Climate control | 0 |
....
| 34 | Leather seats | 0 |
+---------+-----------------+------------+
A simple query to return items with more than one attribute.
SELECT item_id, COUNT(DISTINCT(attr_id)) AS attributes
FROM item GROUP BY item_id HAVING attributes > 1
This gets me a result set like so:
+-----------+------------+
| item_id | attributes |
+-----------+------------+
| 1 | 2 |
| 2 | 2 |
| 3 | 2 |
-- etc. --
However, there's an exception. The attribute
table can hold a tree structure, via parent links in the table. For certain rows, parent_id
can hold the ID of another attribute. There's only one level to this tree. Example:
+---------+-----------------+------------+
| attr_id | value | parent_id |
+---------+-----------------+------------+
| 20 | SE | 21 |
| 21 | M Sport | 0 |
....
I do not want to retrieve items in my original query where, for a pair of associated attributes, they related like attributes 20 & 21.
I do want to retrieve items where:
- the attributes have no parent
- for two or more attributes they are not related (e.g. attributes 23 & 34)
Example result desired, just the item ID:
+------------+
| item_id |
+------------+
| 2 |
+------------+
How can I join against attributes
from items
and exclude these rows?
Do I use a temporary table or can I achieve this from a single query?
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
以下查询将仅提取唯一的项目和属性对(或其父级,如果有),从而消除重复项(这是根据您的要求,属性只能有一个父级,并且父级没有父级)。
因此,使用上述查询作为计数查询的子表将会起作用(与上面的 A 子表使用的方法相同):
我在示例项目表中添加了 3 行以上,以适应可以链接项目的情况仅针对具有父级的属性,而不是父级本身(即项目 3 -> 23 和 3 -> 20),以及 4 -> 20。 23.
运行上述查询仅列出项目 2 和 3,各有 2 个属性。
The following query will extract only unique pairs of item and attribute (or its parent if any), thus eliminating the duplicates (this is per your request that an attribute can have only one parent, and the parent has no parents).
So, using the above query as a subtable for your counting query will work (same approach I used with the A subtable above):
I have added 3 more rows to your example items table, to accommodate the case, where an item can be linked only to an attribute with parent, but not the parent itself (i.e. item 3 -> 23 and 3 -> 20), and 4 -> 23.
Running the above query lists only items 2 and 3 with 2 attributes each.
您可以通过单个查询来实现:
You can achieve that with a single query:
好吧,似乎用一个查询是不可能的,因为我们没有什么可以分组的依据,也没有什么可以排序的。
剩下的一件事是进行一些递归调用,但由于 mysql 中没有递归 SQL,或者如果您的属性数据有一个规则,其中对于所有链接的属性 attr_id <<父 ID。
Well it seems it 's not possible with one query since we have nothing to group by, or nothing to sort on.
The one thing left will be to do some recursive call but since there are no recursive SQL in mysql or if your attribute data have a rule where for all linked attribute attr_id < parent_id.
为了简化这一过程,我使用父属性 ID(如果有)更新了
item
中的所有行。因此,在我的示例
item
表中,更新了属性 ID 后,它看起来像:首先,我得到了一个属性关系列表(子到父):
我在代码中循环了这个并更新了中的行引用子属性的
item
。循环
$update
来更新item
。完成此操作后,我就可以使用原来的查询:我无法让一个查询正常工作。
To simplify this, I updated all rows in
item
with the parent attribute ID, where one is available.So in my example
item
table, with the attribute IDs updated it looks like:First I got a list of attribute relations (child-to-parent):
I looped around this in code and updated the rows in
item
that referenced a child attribute.Loop around
$update
to updateitem
. With this done I was able to use my original query:I couldn't get one query to work.