【发布时间】:2018-05-17 20:48:19
【问题描述】:
我有一张要执行的任务表。每个任务可以有一个依赖项,由一列表示,dep。该列与同一表的id 列形成一个FK。该列可以为空,因此任务可以没有依赖关系。我希望能够对任务列表进行排序,这样一个任务将始终出现在它所依赖的另一个任务之后。
所以,举个这样的例子:
id | name | dep
----------------
1 | A | NULL
2 | B | 1
3 | C | 1
4 | D | 2
有效排序为A,B,C,D、A,C,B,D 和A,C,D,B。这在技术上是一个部分排序。 B 相对于C 的位置并不重要。重要的是“A”在“B”和“C”之前,而“B”在“D”之前。
如果我在 C# 中做这样的事情,我可能会创建一个实现 IComparator<T> 接口的类,并根据对象之间的关系返回 1 或 -1。但似乎 SQL 的 ORDER BY 子句不允许这样的事情。
在标准 SQL 中,如何根据 FK 关系对行进行相对排序?
更新:
我正在使用 Flask-SQLAlchemy(Flask-SQLAlchemy==2.1 和 SQLAlchemy==0.9.9)连接到数据库。为了进行测试,我使用的是内存中的 sqlite db(版本 3.19.3),而在生产中我使用的是 MySQL 5.6。
我曾希望避免 CTE,因为我不熟悉它们,而且我的 MySQL 版本不支持它们。
我的 DDL 看起来像这样(MySQL 方言):
CREATE TABLE `task` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL,
`dep` int(11) DEFAULT NULL,
PRIMARY KEY (`id),
CONSTRAINT `task_ibfk_1` FOREIGN KEY (`dep`) REFERENCES `task` (`id`)
);
我最初的计划是像这样对任务进行排序:
SELECT name FROM task JOIN task AS t2 ON (t2.id = task.dep) ORDER BY (???);
但我怀疑这是不可能的。
【问题讨论】:
-
这需要在大多数 SQL 方言中使用递归 CTE。你用的是什么数据库?
-
这里的需求本质上是递归的。您认为
IComparator<T>可以在这里工作的假设是错误的(请随意尝试 - 输入足够大)。 “标准”排序算法通常依赖于能够独立比较 2 个元素,但这里不是这种情况 -
请使用 DDL、输入数据和预期输出更新您的问题。如果您引用多个表,也包括这些表(您提到了 FK 关系)。还要标记您在问题中使用的数据库。
-
@Amit 我认为你是对的。我在想象这样的事情:gist.github.com/izrik/83317f927c2e86d5c13d2a5483f879ed 这样做的问题是,不相关的任务会被认为是“平等的”,这可能会让一切变得一团糟。