1

例如有 2 个表:

在第一个:对象和父列

object | parent 
-------+---------
object1| null       
object2| object1  
object3| null  

第二个有:对象和参考列

object | reference
-------+---------
object1| null       
object2| null       
object3| object1       

需要查询表以按如下顺序排列:首先是父级,然后是 - 子级,对象具有对父级的引用。

object1
object2
object3

是否可以在一个 SQL 查询中执行或需要在数组中手动​​排序?似乎这是一项经典任务,可能解决方案已经存在于某处?

4

4 回答 4

1

这是你要找的吗?

CREATE TABLE oparen (object varchar(10), parent varchar(10));
CREATE TABLE oref (object varchar(10), ref varchar(10));
INSERT INTO oparen VALUES
    ('object1',null),('object2','object1'),
    ('object3',null),('object4','object2');
INSERT INTO oref VALUES
    ('object1',null),('object2',null),('object3','object1'),
    ('object5','object6'),('object6','object1'),('object7','object4');

WITH hier AS (
    SELECT parent AS obj, 1 AS rank FROM oparen
     WHERE parent IS NOT NULL
    UNION
    SELECT object, 2 FROM oparen
     WHERE parent IS NOT NULL
    UNION
    SELECT object, 3 FROM oref
     WHERE ref IS NOT NULL),
allobj AS (
    SELECT object AS obj FROM oparen
    UNION
    SELECT object FROM oref)
SELECT a.obj, coalesce(h.rank, 4) AS rank
  FROM allobj a LEFT JOIN hier h ON a.obj = h.obj
 ORDER BY coalesce(h.rank, 4), a.obj;

编辑:在以下答案中的改进示例之后,以下查询应该可以解决问题:

WITH parents AS (
    SELECT parent AS obj, 1 AS rank FROM oparen
     WHERE parent IS NOT NULL
    ),
family AS (
    SELECT * FROM parents
    UNION ALL
    SELECT object, 2 FROM oparen op
     WHERE parent IS NOT NULL
       AND NOT EXISTS (SELECT obj FROM parents WHERE obj = op.object)
    ),
hier AS (
    SELECT * FROM family
    UNION ALL
    SELECT object AS obj, coalesce(f.rank + 2, 5) AS rank
      FROM oref LEFT JOIN family f ON oref.ref = f.obj
     WHERE ref IS NOT NULL
    ),
allobj AS (
    SELECT object AS obj FROM oparen
    UNION
    SELECT object FROM oref)
SELECT a.obj, h.rank AS rank
  FROM allobj a LEFT JOIN hier h ON a.obj = h.obj
 ORDER BY h.rank, a.obj;

顶部的测试平台创建根据新要求进行更新。

于 2012-04-19T06:59:19.900 回答
0

以下递归查询有效:

WITH RECURSIVE tables(object, rank) AS (
    SELECT DISTINCT o.object, 1 AS rank FROM oref o
    WHERE o.ref IS NULL
    UNION
    SELECT o.object, t.rank + 1 AS rank
    FROM (SELECT DISTINCT o.object, o.ref FROM oref o
            WHERE ref IS NOT NULL) o, tables t
    WHERE o.ref = t.object AND rank <= t.rank
),
ordered AS (
    SELECT * FROM tables
)
SELECT * FROM tables 
WHERE tables.rank = (SELECT MAX(rank) FROM ordered WHERE ordered.object = tables.object)
ORDER BY rank;

有任何意见、问题、反对意见、建议吗?;)

于 2012-05-02T10:06:27.270 回答
0

不,不起作用:检查其他数据并简化使用,仅通过 oref 表内容:

INSERT INTO oref VALUES
('object1',null),('object2',null),('object3','object1'),
('object5','object6'),('object6','object1'),('object7','object4'), ('object4','object5');

WITH family AS (
    SELECT object AS obj, 1 AS rank FROM oref
     WHERE ref IS NULL
    ),
hier AS (
    SELECT * FROM family
    UNION ALL
    SELECT object AS obj, coalesce(f.rank + 2, 5) AS rank
      FROM oref LEFT JOIN family f ON oref.ref = f.obj
     WHERE ref IS NOT NULL
    ),
allobj AS (
    SELECT object AS obj FROM oref)
SELECT a.obj, h.rank AS rank
  FROM allobj a
  LEFT JOIN hier h ON a.obj = h.obj
 ORDER BY h.rank, a.obj;

认为需要在这里使用递归查询。将在这里写和发布。

于 2012-04-29T21:03:11.573 回答
0

我插入了以下数据:

INSERT INTO oparen VALUES
    ('object1',null),('object2','object1'),('object3',null),('object4','object2');
INSERT INTO oref VALUES
    ('object1',null),('object2',null),('object3','object1'),('object5','object6'),('object6','object1');

顺序不正确,object2 列出了两次。obj 上的 DISTINCT 也破坏了顺序。应该去 6 然后 5。

于 2012-04-20T06:04:33.677 回答