如何使用连接从两个表中 select 分层记录
How to select hierarchical records from two tables using join
实际上我想 select 匹配来自两个 table 的记录和第一个 table
的分层数据
我有两个 table:
tmpos_category table 与 列 (category_refid(pk),category_name,parent_ref_id)。我在其中存储分层数据。
tmpos_menu_child table 与 列 (id(pk),title,category_ref_ids(fk))。 category_ref_ids 来自 tmpos_menu_child 的字段 table 引用了 tmpos_category table.[=16 的 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 table 和 tmpos_menu_child table 时,我将获得所有不同的匹配类别,但我也想要 selected类别父记录
因此,当在 category table
上将此架构与 parent_ref_id
一起使用时,很难向上移动层次结构并获取所有祖先类别,而无需为每个 [ 编写硬编码 1 连接的查询=39=].
如果你只会有 2 或 3 代(例如 child、parent、grandparent)那么这没问题,但有更多(或可变级别)它会变得混乱。一种解决方案是使用 "recursive syntax",但据我所知并非所有 SQL 实现都支持它。
Bill Karwin 有一个出色的幻灯片,其中详细介绍了您的架构的 pros/cons(通常称为 "adjacency lists")。
您可以在此处找到幻灯片 6-17:
https://www.slideshare.net/billkarwin/models-for-hierarchical-data
他很好地详细说明了您的问题,并提供了其他几种建模层次结构的策略,如果您最终在使用当前模式时遇到问题。我个人喜欢那副牌中详细介绍的最后一张,它被称为 "closure table"
编辑
如果您实际上只是想包含一个或两个 parent 级别,那么您的查询将看起来与任何连接 3 个或更多 table 的查询非常相似,只是您必须将 categories
table 加入自身。如果你 google "join a table to itself" 或类似的
应该很容易找到这样的例子
如果您的层次结构中只能有 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(常见的 table 表达式)完成的。
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 和 [=35] 不允许=] 服务器.
更新
来自:
i want there parents as record(in seperate row)
要将父记录作为单独的行获取,运行 查询两次并与 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
实际上我想 select 匹配来自两个 table 的记录和第一个 table
的分层数据我有两个 table:
tmpos_category table 与 列 (category_refid(pk),category_name,parent_ref_id)。我在其中存储分层数据。
tmpos_menu_child table 与 列 (id(pk),title,category_ref_ids(fk))。 category_ref_ids 来自 tmpos_menu_child 的字段 table 引用了 tmpos_category table.[=16 的 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 table 和 tmpos_menu_child table 时,我将获得所有不同的匹配类别,但我也想要 selected类别父记录
因此,当在 category table
上将此架构与 parent_ref_id
一起使用时,很难向上移动层次结构并获取所有祖先类别,而无需为每个 [ 编写硬编码 1 连接的查询=39=].
如果你只会有 2 或 3 代(例如 child、parent、grandparent)那么这没问题,但有更多(或可变级别)它会变得混乱。一种解决方案是使用 "recursive syntax",但据我所知并非所有 SQL 实现都支持它。
Bill Karwin 有一个出色的幻灯片,其中详细介绍了您的架构的 pros/cons(通常称为 "adjacency lists")。
您可以在此处找到幻灯片 6-17:
https://www.slideshare.net/billkarwin/models-for-hierarchical-data
他很好地详细说明了您的问题,并提供了其他几种建模层次结构的策略,如果您最终在使用当前模式时遇到问题。我个人喜欢那副牌中详细介绍的最后一张,它被称为 "closure table"
编辑
如果您实际上只是想包含一个或两个 parent 级别,那么您的查询将看起来与任何连接 3 个或更多 table 的查询非常相似,只是您必须将 categories
table 加入自身。如果你 google "join a table to itself" 或类似的
如果您的层次结构中只能有 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(常见的 table 表达式)完成的。
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 和 [=35] 不允许=] 服务器.
更新
来自
i want there parents as record(in seperate row)
要将父记录作为单独的行获取,运行 查询两次并与 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