实际上我想从两个表中选择匹配的记录,并从第一个表中选择分层数据
我有两个表:
tmpos_category表,其中包含列(category_refid(pk),category_name,parent_ref_id)。我在其中存储分层数据。
tmpos_menu_child表具有列(id(pk),title,category_ref_ids(fk))。 tmpos_menu_child表中的category_ref_ids字段引用了tmpos_category表中的 category_refid字段。
this is a tmpos_category table with hierarchical categories
tmpos_menu_child table with category_ref_ids as fk refrances category(category_refid ) column
SELECT DISTINCT ct.category_name,ct.category_refid,ct.parent_ref_id
from tmpos_category ct
JOIN tmpos_menu_child tmc
ON ct.category_refid = tmc.category_ref_ids
现在我的问题是,当我加入tmpos_category表和tmpos_menu_child表时,我将获得所有不同的匹配类别,但我还希望选择类别的父记录
答案 0 :(得分:0)
因此,当将此架构与parent_ref_id
上的category table
一起使用时,将很难向上移动层次结构并获得所有祖先类别,而无需编写每个父代都要硬编码1加入的查询。 / p>
如果您只有2或3代(例如孩子,父母,祖父母),那么这可以,但是如果使用更多(或可变级别),可能会变得凌乱。一种解决方案是使用“递归语法”,但据我所知并不是所有的SQL实现都支持它。
Bill Karwin具有出色的幻灯片组,详细介绍了架构的优缺点(通常称为“邻接列表”)。
您可以在幻灯片6-17上找到它:
他相当不错地详细说明了您的问题,并且如果您最终无法使用当前架构,则可以提供其他几种建模层次结构的策略。我个人喜欢该平台中最后一个细节,称为“封闭表”
编辑
实际上,如果您仅尝试包含一个或两个父级,那么您的查询将与连接3个或更多表的任何查询非常相似,只需要将categories
表与其自身连接即可。如果您通过Google“将表自身连接”或类似的方法,应该很容易找到此类示例
答案 1 :(得分:0)
如果您的层次结构中只能有2个级别,即父级本身不能有父级,那么两个JOIN都可以。
SELECT i.id AS item_id, i.title AS item_title
, c.category_refid, c.category_name
, c.parent_ref_id, p.category_name AS parent_name
FROM tmpos_menu_child i
JOIN tmpos_category c ON c.category_refid = i.category_ref_ids
LEFT JOIN tmpos_category p ON p.category_refid = c.parent_ref_id
如果层次结构可以很深,则应使用层次结构查询,在大多数DBMS中,它是通过递归CTE(公用表表达式)完成的。
WITH RECURSIVE Item_and_Cat (item_id, item_title, category_level,
category_refid, category_name, parent_ref_id) AS (
SELECT i.id AS item_id, i.title AS item_title
, c.category_refid, c.category_name
, 1 AS category_level, c.parent_ref_id
FROM tmpos_menu_child i
JOIN tmpos_category c ON c.category_refid = i.category_ref_ids
UNION ALL
SELECT i.item_id, i.item_title
, p.category_refid, p.category_name
, i.category_level + 1 AS category_level, p.parent_ref_id
FROM Item_and_Cat i
JOIN tmpos_category p ON p.category_refid = i.parent_ref_id
)
SELECT item_id, item_title, category_refid, category_name, category_level
FROM Item_and_Cat
注意: PostgreSQL和MySQL需要RECURSIVE
关键字,而Oracle DB和SQL Server则不允许。
更新
来自comment:
我希望有父母作为记录(在单独的行中)
要使父记录作为单独的行,请运行两次查询,然后与UNION
组合。
SELECT i.id AS item_id, i.title AS item_title
, c.category_refid, c.category_name, 0 AS is_parent
FROM tmpos_menu_child i
JOIN tmpos_category c ON c.category_refid = i.category_ref_ids
UNION ALL
SELECT i.id AS item_id, i.title AS item_title
, p.category_refid, p.category_name, 1 AS is_parent
FROM tmpos_menu_child i
JOIN tmpos_category c ON c.category_refid = i.category_ref_ids
JOIN tmpos_category p ON p.category_refid = c.parent_ref_id