2012-04-01 94 views
3

我有2个表:edgesusersMySQL的顶点与边缘相交

edges(与约束:ID1 < ID2):

id1 
name1 
id2 
name2 

users

id 
name 

我想得到只有边的结果集(id1,name1,id2,name2),使得BOTH id1和id2在users表中。这看起来很简单,但我很难得到它。我的尝试:

SELECT 
    e.id1 AS id1, 
    e.name1 AS name1, 
    e.id2 AS id2, 
    e.name2 AS name2 
FROM 
    edges AS e, 
    users AS u 
WHERE u.id = e.id1 

UNION 

SELECT 
    e.id1 AS id1, 
    e.name1 AS name1, 
    e.id2 AS id2, 
    e.name2 AS name2 
FROM 
    edges AS e, 
    users AS u 
WHERE u.id = e.id2 

任何指针?

+0

你有什么问题? – Arion 2012-04-01 17:57:57

回答

1

使用两个内层try JOINS这样的:

SELECT * FROM edges e 
JOIN users u1 ON e.name1 = u1.name 
JOIN users u2 ON e.name2 = u2.name 
+0

这个工程!它有点慢,但我认为第一个JOIN是一个'O(| V | * | E |)'操作,所以这些连接在一起会产生'O(| V | * | E |^2) '?可能是我们在这里能做的最好的? – lollercoaster 2012-04-01 18:15:56

+0

在三个名称字段上创建索引以提高性能。 – jordeu 2012-04-01 18:19:57

+0

我不确定,但我认为如果你的用户表比边缘表小,你可以先做一个RIGHT JOIN然后LEFT JOIN,它会加快查询速度。 – jordeu 2012-04-01 18:22:54

0

也许是这样的:

SELECT 
    e.id1 AS id1, 
    e.name1 AS name1, 
    e.id2 AS id2, 
    e.name2 AS name2 
FROM 
    edges AS e 
WHERE EXISTS 
    (
     SELECT 
     NULL 
     FROM 
     users AS u 
     WHERE 
     u.id = e.id1 
     AND u.id = e.id2 
) 
+0

嗯,这将返回空集? – lollercoaster 2012-04-01 18:05:35

+0

不会。它返回有用户的eges。 – Arion 2012-04-01 18:34:00

1

试试这个:

select e.id1, e.name1, e.id2, e.name2 from edges e 
join users u1 on e.id1 = u1.id 
join users u2 on e.id2 = u2.id 
+0

是的,这是@ jordeu的,但在这里你摆脱了重复的列,这是所期望的。我在上面想到的对运行时的任何想法? – lollercoaster 2012-04-01 18:17:53