例如有2个表:
第一名:对象&父列
object | parent
-------+---------
object1| null
object2| object1
object3| null
第二名:对象&参考专栏
object | reference
-------+---------
object1| null
object2| null
object3| object1
需要按以下顺序查询表:父是第一个,然后是 - 子(s),具有父对象引用的对象。
object1
object2
object3
是否可以在一个SQL查询中执行或需要在数组中手动排序?似乎这是一项经典任务,可能解决方案已存在于某个地方?
答案 0 :(得分: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;
根据新要求更新顶部的测试平台创建。
答案 1 :(得分: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。
答案 2 :(得分: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;
认为需要在这里使用递归查询。将在这里写和发表。
答案 3 :(得分: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;
任何评论,问题,异议,主张? ;)