这里深入研究一些复杂的 SQL。我想创建一个视图/虚拟表。
我有一个对象表。看起来像这样(所有值都是 int)
| 编号 | 父 ID | 外键 | 开始日期 | 结束日期 |
CREATE TABLE objects (
id int AUTO_INCREMENT PRIMARY KEY,
parent_id INT(11),
foreign_key INT(11),
start_date INT(11),
end_date INT(11)
);
INSERT INTO objects
VALUES
(1, 0, 1, 1638930577, 1638930578),
(2, 1, 1, 1638930578, 1638930578),
(3, 2, 1, 1638930578, 1638930578),
(4, 0, 2, 1638930576, 1638930578),
(5, 4, 2, 1638930578, 1638930578),
(6, 5, 2, 1638930578, 1638930578),
(7, 0, 1, 1638930574, 1638930578),
(8, 7, 1, 1638930578, 1638930578),
(9, 7, 1, 1638930578, 1638930579)
Run Code Online (Sandbox Code Playgroud)
我想创建一个看起来像
| 编号 | 开始日期 | 结束日期 | 对象数量 |
我以前从未使用过 SQL 视图,对于我的情况来说,它比编写代码更理想。这可能吗?我的主要疑虑是,当我在代码中执行此操作时,我需要给它一个 object_id 来启动,真的不知道如何获取一组具有不为 0 的相同父 id 的对象。
谢谢
PS 使用 MySQL/Maria 最新版本,但方言可能不是非常重要。
SQL小提琴:http://sqlfiddle.com/#!9/429570/1
时间表提供的新视图的返回结果应如下所示
| ID | 外键 | 开始日期 | 结束日期 | 对象数量 |
|---|---|---|---|---|
| 1 | 1 | 1638930577 | 1638930578 | 3 |
| 2 | 2 | 1638930576 | 1638930578 | 3 |
| 3 | 1 | 1638930574 | 1638930579 | 3 |
返回结果应该像这样构建:
objectGroup。新视图中的项目包括
看起来您的数据有三层深度(可能更深)。您可以使用递归从父级遍历到子级再到孙级。不幸的是,这需要 MySQL 8 或更高版本:
with recursive rcte as (
/***
select all topmost level rows
the id and foreign_key of the parent will be "copied" to all children and grandchildren
the last id column is needed to link the next set of rows with this one
***/
select id as group_id, foreign_key, start_date, end_date, id
from objects
where parent_id = 0
union all
/***
p is the set of rows from previous iteration (this is how recursive cte works)
c is the set of rows that are direct children of p
p.group_id and p.foreign_key are copied from parent (which in turn were copied from their parent and so on)
***/
select p.group_id, p.foreign_key, c.start_date, c.end_date, c.id
from rcte as p
join objects as c on c.parent_id = p.id
)
/***
all "object groups" now have same group_id and foreign_key
we just need to group by
***/
select group_id, foreign_key, min(start_date) as start_date, max(end_date) as end_date, count(*) as number_of_objects
from rcte
group by group_id, foreign_key
Run Code Online (Sandbox Code Playgroud)
您可能需要考虑其他模型来存储数据。邻接列表(您正在使用的)更容易维护(插入、更新、删除),但在没有递归的情况下很难查询(例如查找给定节点的子树)。嵌套集合模型是一个很好的替代方案,它更易于查询,但难以维护。物化路径模型是另一个候选模型,它易于查询但难以维护(使用数组数据类型更容易实现,但没有引用完整性)。