2014-09-20 70 views
1

我有2个表SQL插入,使所有用户的朋友与所有

1) USERS - List of all users 
2) FRIENDS - List of users who are friends with each other 

我要让所有的用户朋友与所有其他用户。所以基本上我需要在朋友表中插入所有用户信息。

USERS表列

1) id - user id of the user 
2) name - user name 

朋友表列

1) user_id 
2) friend_id 

问:

我想通过一个把来自用户的表中的一个的用户,做批量插入到FRIENDS表中对于不是朋友的用户。

我知道我可以用JOIN逐个检查并做一些事情。但我不认为这是简单而正确的做法。需要来自专家的一些意见。

注意: user_id和friend_id中的值可以互换,它仍然表示它们是朋友。不应该有像(1,2)和(2,1)这样的组合。

SQL小提琴:http://sqlfiddle.com/#!2/07b2d9/1

对于所提供的小提琴,所有用户都必须做出的朋友为其他用户忽略谁已经是朋友了。

+1

为什么你会想要一个完整的朋友图?你有什么理由不先放弃朋友表,只是添加所有组合? – andy 2014-09-20 17:32:17

+0

好主意。 +1。但即使在这种情况下,我们也不需要SQL来执行该操作。而且,无论何时新用户加入,它都会强制一次又一次地删除整个表。 – Purus 2014-09-20 17:40:48

+0

如果您省略cdhowie的答案中的where子句,您会得到完全相同的SQL。我的第一个问题是为什么你需要一个包含所有连接的表格,因为它没有包含任何有用的信息。 – andy 2014-09-20 17:43:09

回答

1

这应该做的伎俩:

insert into friends (user_id, friend_id) 

select a.id as user_id, 
     b.id as friend_id 

-- Join users to itself. The join constraint results in all of the combinations of 
-- two friend IDs, rather than all of the permutations. 
from users a 
inner join users b on a.id < b.id 

-- Remove rows from the results that have a matching row in the friends table. 
where not exists (
    select f.user_id 
    from friends f 
    where ((f.user_id = a.id and f.friend_id = b.id) or 
     (f.user_id = b.id and f.friend_id = a.id)) 
); 
+0

在这个SQL中,哪个地方最适合添加一个条件来仅为USERS表中的特定用户插入行?说我想插入朋友为用户ID 3. – Purus 2014-09-20 17:38:05

+0

@Purus'其中(a.id = 3或b.id = 3),并且不存在...' – cdhowie 2014-09-20 17:38:57

+0

所以亲爱的朋友们,我现在应该怎么做,准确地考虑评论@ spencer7593? – Purus 2014-09-20 17:46:21

1

要确定是不是一个“朋友”与其他用户的用户的所有组合,假设你只想要一个行(例如(1,4))来表示:友谊:而不是两行(例如(1.4)(4,1)

SELECT u.id AS user_id 
    , t.id AS friend_id 
    FROM users u 
    JOIN users t 
    ON t.id > u.id 
    LEFT 
    JOIN friends f 
    ON f.user_id = u.id 
    AND f.friend_id = t.id 
    LEFT 
    JOIN friends g 
    ON g.user_id = t.id 
    AND g.friend_id = u.id 
WHERE f.user_id IS NULL 
    AND g.user_id IS NULL 

这种查询可以通过INSERT INTO friends (user_id, friend_id)前面那些行插入的朋友表。

用户表与其自身的连接获取所有组合,但我们希望排除user_idfriend_id具有相同值的行;我们只需要关系的一方,因此我们可以排除user_id> friend_id所在的行。

要排除朋友表中已有的行,我们可以使用反连接模式。因为我们只需要两个可能的行(1,4)或(4,1)中的一个,并且其中的任何一个可能已经存在,我们都会执行这两种检查。


要为单个用户做到这一点,添加:

AND (u.id = 4 OR t.id = 4) 
+0

我相信最后2行应该改变以反映正确的列名。由于此错误而不执行。 – Purus 2014-09-20 17:33:11

+0

@Purus:很好。回答更新以反映正确的列名称。 – spencer7593 2014-09-20 17:38:51

+0

使用更多连接去影响性能,对吧? – Purus 2014-09-20 17:46:54

相关问题