Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/81.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql SQL-如何相对地对行进行排序?_Mysql_Sql_Sqlite - Fatal编程技术网

Mysql SQL-如何相对地对行进行排序?

Mysql SQL-如何相对地对行进行排序?,mysql,sql,sqlite,Mysql,Sql,Sqlite,我有一个要执行的任务表。每个任务可以有一个依赖项,由列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。从技术上

我有一个要执行的任务表。每个任务可以有一个依赖项,由列
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
接口的类,并根据对象之间的关系返回
1
-1
。但是SQL的
orderby
子句似乎不允许这样的事情

在标准SQL中,如何根据FK关系对行进行相对排序?


更新: 我正在使用Flask SQLAlchemy(
Flask SQLAlchemy==2.1
SQLAlchemy==0.9.9
)连接到数据库。在测试中,我使用内存中的sqlite db(版本
3.19.3
),在生产中,我使用MySQL 5.6

我本来希望避免使用CTE,因为我不熟悉它们,而且我的MySQL版本不支持它们

我的DDL看起来像这样(MySQL方言):

我最初的计划是将任务分类如下:

SELECT name FROM task JOIN task AS t2 ON (t2.id = task.dep) ORDER BY (???);

但我怀疑这是不可能的。

编辑:这是为Microsoft SQL Server编写的,它可能无法传输到操作所使用的DBMS。我把它放在这里作为参考


在我们等待您更新正在使用的DBMS时,我将把它扔到戒指上。正如评论员指出的那样,它使用递归CTE来根据与父任务的关系确定每个任务所在的级别(最终是我们的排序顺序)。我对您的输入数据做了一些修改,以表明它是正确排序的,因为您的数据已经处于理想的顺序

WITH Test(id, name, dep) AS
(
    SELECT 1, 'A', NULL UNION
    SELECT 2, 'B', 4 UNION
    SELECT 3, 'C', 2 UNION
    SELECT 4, 'D', 1 
)
, RecursiveCTE AS
(
  SELECT id, name, dep, 0 AS level
  FROM Test
  WHERE dep IS NULL
  UNION ALL
  SELECT i.id, i.name, i.dep, level + i.id
  FROM Test i
  INNER JOIN RecursiveCTE c ON c.id = i.dep
)
SELECT id, name, dep
FROM RecursiveCTE
ORDER BY level;
输出:

id name dep
-- ---- ----
1无效
4d1
2 B 4
3 C 2

在大多数SQL方言中,这需要递归CTE。您使用的是什么数据库?这里的需求本质上是递归的。您认为
IComparator
在这里可以工作的假设是错误的(请随意尝试-输入足够大)。“标准”排序算法通常依赖于能够独立比较2个元素,但这里不是这种情况。请使用DDL、输入数据和预期输出更新您的问题。如果您正在引用多个表,那么也包括这些表(您提到了FK关系)。同时标记您在问题中使用的数据库。@Amit我认为您是对的。我在想象这样的事情:问题是,不相关的任务会被认为是“平等的”,这可能会把一切搞得一团糟。我会试试这个。我不熟悉CTE,所以可能会有一个学习曲线。@Cory,这对我很有用。我甚至尝试了其他样本数据集,得到了正确的顺序。出于好奇,在计算级别时,为什么要使用
level+i.id
而不是
level+1
?订购不应依赖于id值,对吗?您可以使用
+1
+i.id
只是一种安全检查,以确保排名基于
id
WITH Test(id, name, dep) AS
(
    SELECT 1, 'A', NULL UNION
    SELECT 2, 'B', 4 UNION
    SELECT 3, 'C', 2 UNION
    SELECT 4, 'D', 1 
)
, RecursiveCTE AS
(
  SELECT id, name, dep, 0 AS level
  FROM Test
  WHERE dep IS NULL
  UNION ALL
  SELECT i.id, i.name, i.dep, level + i.id
  FROM Test i
  INNER JOIN RecursiveCTE c ON c.id = i.dep
)
SELECT id, name, dep
FROM RecursiveCTE
ORDER BY level;