我在oracle9i的数据库中有这个表:
CREATE TABLE involved_in
(
rid number,
aid number NOT NULL,
fid number NOT NULL,
role varchar(80),
note varchar(80),
job varchar(35),
PRIMARY KEY(rid),
FOREIGN KEY(fid) REFERENCES production(pr_id),
FOREIGN KEY(aid) REFERENCES person(pid)
);
其中包含有关在电影(fid)中工作的演员(援助)的数据。
我想要做的与制定Bacon number
类似除了我的凯文培根以获得援助517635而闻名。
我不知道如何计算(仅使用SQL语句)我必须连接给定actor(通过另一个辅助)的actor数量,以找到与517635的连接。
查询的结果可能是给定演员必须连接的所有演员的列表,以获取我的家伙或只是一个号码。
为此,我认为我必须先获得517635所有参与者的所有参与者,并且因为与他直接合作会产生1。这张桌子不是太大,但足够大,可以让它变得不可靠。
例子,让我们说布拉德皮特是我的517635.他与安吉丽娜朱莉一起在史密斯先生和史密斯夫人身上工作,这将使她成为第一名。如果布拉德皮特从未在任何电影中与布鲁斯威利斯合作过(让& #39; s说的是这样的情况)但安吉丽娜朱莉与他在一起然后布鲁斯威利斯'布拉德皮特的数字是2。
在我的查询中,如果给定的数字是安吉丽娜,结果将是: "布拉德皮特1"或者只是" 1" 如果给定的数字是Willis'结果将是: "安吉丽娜朱莉 布拉德皮特2" 要么 " 2" 表中的内容示例:
INSERT INTO involved_in(rid, aid, fid, role, note, job) VALUES(1, 33, 1584953, 'Himself', 'NULL', 'actor');
INSERT INTO involved_in(rid, aid, fid, role, note, job) VALUES(2, 1135, 1999660, 'Himself', 'NULL', 'actor');
INSERT INTO involved_in(rid, aid, fid, role, note, job) VALUES(3, 1135, 2465724, 'Himself', 'NULL', 'actor');
INSERT INTO involved_in(rid, aid, fid, role, note, job) VALUES(4, 6003, 2387806, 'Himself', '(archive footage)', 'actor');
INSERT INTO involved_in(rid, aid, fid, role, note, job) VALUES(5, 13011, 1935123, 'Himself', 'NULL', 'actor');
我没有任何想法,我对SQL完全陌生,我所能想到的只会导致带有变量的无限循环来计算循环次数。 关于从哪里开始的任何想法,幸运的是,结束了吗?
答案 0 :(得分:2)
如果没有样本数据,这很难验证,但以下答案至少在语法上是正确的。
你想要的是一个递归查询。在Oracle中有以下方法:使用公用表表达式(CTE)(即with
子句);或使用connect by
子句。 CTE是SQL标准,connect by
是专有的,但我发现connect by
不那么混乱,所以我将使用它(9i中也不支持递归CTE)。
SELECT aid, MIN (lvl) AS distance
FROM (SELECT ii2.aid, LEVEL AS lvl
FROM involved_in ii1
JOIN involved_in ii2
ON ii1.fid = ii2.fid AND ii1.aid <> ii2.aid
START WITH ii1.aid = 517635
CONNECT BY NOCYCLE ii1.aid = PRIOR ii2.aid)
GROUP BY aid
aid
的{{1}}相互连接。fid
子句将每组连接的connect by
连接到另一组aid
。aid
子句阻止无限递归。nocycle
是一个关键字,它为我们提供了递归发生的次数。我们必须得到最小值,因为任何给定的level
都可以通过多条路径连接到起始aid
。aid
添加到and level <= 100
子句中(在这种情况下,将结果限制为100或更小的距离)。正如评论中所指出的,9i不支持connect by
。此外,运行此查询时,OP的临时空间不足。这两者实际上是无关的:如果发生循环,Oracle将抛出错误;这意味着在找到循环之前服务器的临时空间不足。我认为没有任何好办法解决这些问题。
可以指定一个终点(在某种程度上)。您可以将nocycle
AND ii1.aid <> 2
作为端点的2
添加到aid
子句中。这将导致查询在遇到该值时停止导航分支。然而,这可能对上述问题没有帮助,因为它只会使找到所提供值的分支短路。它仍然必须评估所有其他分支,以防值在某处。
答案 1 :(得分:1)
最好的方法是使用分层查询。
Oracle(即使在9i版本中)也有CONNECT BY子句。 http://docs.oracle.com/cd/B19306_01/server.102/b14200/queries003.htm
结合START WITH和LEVEL,这变得非常简单。
示例:
SELECT last_name, employee_id, manager_id, LEVEL
FROM employees
START WITH employee_id = 100
CONNECT BY PRIOR employee_id = manager_id
ORDER SIBLINGS BY last_name;