目前我有以下Model
:
SELECT m.city_area_id AS city_area_id
FROM menus m
JOIN oc_category c ON (m.id = c.menu_id)
JOIN oc_category oc ON (oc.parent_id = c.category_id)
JOIN oc_product_to_category ptc ON
ptc.category_id = oc.category_id AND
ptc.product_id = $dish_id
此模型的预期行为是找到给出菜肴的城市区域ID。
它的工作原理如下:
oc_product_to_category
查找我们的产品[我们的输入]类别ID。 category_id
,我们前往oc_category
查找此特定产品的parent_id
。 一旦您达到了最顶级的类别ID,就会有menu_id
[menu_id
为0
,如果它不是最高category_id
,而parent_id
也是0
,因为我们没有更多的父母可供我们使用。
获得menu_id
后,我们就可以找到此菜单的城市区域ID。
以下是category_id
行parent_id
的示例。如您所知,menu_id
为0
,parent_id
为非零值。
+-------------+-------+-----------+-----+--------+------------+--------+---------------------+---------------------+------------------+---------+
| category_id | image | parent_id | top | column | sort_order | status | date_added | date_modified | visible_official | menu_id |
+-------------+-------+-----------+-----+--------+------------+--------+---------------------+---------------------+------------------+---------+
| 784 | NULL | 783 | 0 | 0 | 1 | 1 | 0000-00-00 00:00:00 | 0000-00-00 00:00:00 | 1 | 0 |
+-------------+-------+-----------+-----+--------+------------+--------+---------------------+---------------------+------------------+---------+
我的问题:
我当前的SQL查询适用于每个category_id
,只有一个parent_id
级别可以遍历。因此,对于那些具有两个父category_id
s [而不是一个]的产品,我的脚本将返回一个空集。
我的问题是 - 无论这个特定类别ID有多少父母,我如何智能地从一个叶子遍历到最近的父母?
编辑:看起来我的SQL行的格式化都是拙劣的。我不知道如何将水平滚动条添加到我的代码块=(
答案 0 :(得分:1)
如果我了解您要执行的操作,则根据某些条件从ptc
开始设置一组特定的行,例如
SELECT ptc.*
FROM oc_product_to_category ptc
WHERE ptc.product_id = $dish_id
然后你想获得相关的oc
...
JOIN oc_category oc
ON oc.category_id = ptc.category_id
如果那不是顶级oc
,你想得到它的父母......
JOIN oc_category a1
ON a1.category_id = oc.parent_id
如果那不是顶级,你想得到它的父母......
JOIN oc_category a2
ON a2.category_id = a1.parent_id
依此类推,直到你获得最多的父母。
在单个查询中执行此操作的一种方法是首先确定树的最大可能深度,然后使用外部联接操作返回每个级别的父级...
SELECT ptc.*
FROM oc_product_to_category ptc
JOIN oc_category a0
ON a0.category_id = ptc.category_id
LEFT JOIN oc_category a1 ON a1.category_id = oc.parent_id
LEFT JOIN oc_category a2 ON a2.category_id = a1.parent_id
LEFT JOIN oc_category a3 ON a3.category_id = a2.parent_id
LEFT JOIN oc_category a4 ON a4.category_id = a3.parent_id
WHERE ptc.product_id = $dish_id
现在的诀窍是确定哪些表引用(a1,a2,a3,a4)返回最顶层。
一种方法是使用一个表达式,从上到下测试每个级别,以确定返回非NULL值的最高级别。例如:
CASE
WHEN a4.category_id IS NOT NULL THEN a4.menu_id
WHEN a3.category_id IS NOT NULL THEN a3.menu_id
WHEN a2.category_id IS NOT NULL THEN a2.menu_id
WHEN a1.category_id IS NOT NULL THEN a1.menu_id
WHEN a0.category_id IS NOT NULL THEN a0.menu_id
END
您可以在谓词中使用该表达式的结果来加入menus
表
LEFT JOIN menus m ON m.id = expr
因此,整个查询可能看起来像这样:
SELECT m.city_area_id as city_area_id
FROM oc_product_to_category ptc
JOIN oc_category oc ON oc.category_id = ptc.category_id
LEFT JOIN oc_category a0 ON a0.category_id = oc.parent_id
LEFT JOIN oc_category a1 ON a1.category_id = a0.parent_id
LEFT JOIN oc_category a2 ON a2.category_id = a1.parent_id
LEFT JOIN oc_category a3 ON a3.category_id = a2.parent_id
LEFT JOIN oc_category a4 ON a4.category_id = a3.parent_id
LEFT JOIN menus m
ON m.id =
CASE
WHEN a4.parent_id = 0 THEN a4.menu_id
WHEN a3.parent_id = 0 THEN a3.menu_id
WHEN a2.parent_id = 0 THEN a2.menu_id
WHEN a1.parent_id = 0 THEN a1.menu_id
WHEN a0.parent_id = 0 THEN a0.menu_id
END
WHERE ptc.product_id = $dish_id
此示例查询将仅查找最多四个级别的最顶级父级;如果您的层次结构具有更大的深度,那么您需要按照相同的模式将其扩展到更多级别...
LEFT JOIN oc_category a5 ON a5.category_id = a4.parent_id
LEFT JOIN oc_category a6 ON a6.category_id = a5.parent_id
您需要扩展返回menu_id
的表达式,以检查是否从这些级别返回了一行。
(在我的实现中,我通常使用parent_id
列的NULL值来指示最顶层的节点。如果您的层次结构以不同的方式实现,则使用0
的值作为parent_id,您可以需要使用不同的表达式来测试最高级别,但表达式将遵循相同的模式:
CASE
WHEN a4.parent_id = 0 THEN a4.menu_id
WHEN a3.parent_id = 0 THEN a3.menu_id
WHEN a2.parent_id = 0 THEN a2.menu_id
WHEN a1.parent_id = 0 THEN a1.menu_id
WHEN a0.parent_id = 0 THEN a0.menu_id
END