合并两个复杂的查询

时间:2010-07-21 20:48:04

标签: php sql mysql intersection

我最终做的是接受两个SQL查询并使用PHP中的array_intersect()来过滤掉结果:

$sql1 = 'SELECT z.*, u.username, u.user_colour, u.username_clean, u.user_avatar, u.user_avatar_type
    FROM ' . ZEBRA_TABLE . ' z, ' . USERS_TABLE . ' u
    WHERE (( z.user_id = ' . $user->data['user_id'] . '
        AND z.friend = 1
        AND u.user_id = z.zebra_id )
            OR ( z.zebra_id = ' . $user->data['user_id'] . '
                AND z.friend = 1
                AND u.user_id = z.user_id ))
    ORDER BY u.username_clean ASC';

$sql2 = 'SELECT z.*, u.username, u.user_colour, u.username_clean, u.user_avatar, u.user_avatar_type
    FROM ' . ZEBRA_TABLE . ' z, ' . USERS_TABLE . ' u
    WHERE (( z.user_id = ' . $user_id . '
        AND z.friend = 1
        AND u.user_id = z.zebra_id )
            OR ( z.zebra_id = ' . $user_id . '
                AND z.friend = 1
                AND u.user_id = z.user_id ))
    ORDER BY u.username_clean ASC';

两个查询的结构相同,唯一的区别是$user->data['user_id](第一人称)在第二个查询中被$user_id(第二人称)替换。我想要检索两个用户有共同点的朋友。任何人都可以将其合并到一个查询中,这样我就不必使用两个查询并调用array_intersect()吗?

2 个答案:

答案 0 :(得分:4)

嗯,你总是可以只查询两个:

$sql = 'SELECT a.* 
    FROM ('.$sql1.') AS a 
    JOIN ('.$sql2.') AS b ON a.user_id = b.user_id AND a.username = b.username';

您可能希望将u.user_id添加到两个查询u.user_id AS u_user_id的字段列表中,然后将第二个连接子句从a.username = b.username更改为a.u_user_id = b.u_user_id ...

编辑:现在我真的看得更近了,这两个查询几乎完全相同......为什么不做这样的事情(将where子句替换为此):

WHERE z.friend = 1 
   AND (
       ( z.user_id = '.$user_id.' AND u.user_id = z.zebra_id )
        OR
       (z.zebra_id = '.$user_id.' AND u.user_id = z.user_id )
   ) AND (
       ( z.user_id = '.$user->data['user_id'].' AND u.user_id = z.zebra_id )
        OR
       (z.zebra_id = '.$user->data['user_id'].' AND u.user_id = z.user_id )
   ) 

这应该会给你两个查询相交的结果,并且更快,因为它可以更好地进行优化(希望如此)......

哦,他们在阻止的地方不同,因为有一些情况z.user_id匹配$user_id,但z.zebra_id匹配$user->data['user_id'] ...所以而不是列出所有排列,我只是这样摆出来......

答案 1 :(得分:1)

您可以通过将用户表链接到斑马表两次来选择与两个用户成为朋友的用户:

SELECT u.username, u.user_colour, u.username_clean, u.user_avatar, u.user_avatar_type 
FROM users u
JOIN zebra z1 ON z1.friend=1 AND (
                   (u.user_id = z1.user_id AND z1.zebra_id = @user_id1)
                   OR (u.user_id = z1.zebra_id AND z1.user_id = @user_id1)
                 )
JOIN zebra z2 ON z2.friend=1 AND (
                   (u.user_id = z2.user_id AND z2.zebra_id = @user_id2)
                   OR (u.user_id = z2.zebra_id AND z2.user_id = @user_id2)
                 )
ORDER BY u.username_clean ASC

JOIN获取users表中的所有行以及zebra表中的所有行,并查找满足ON子句的组合。在这种情况下,第一个联接会查找与@user_id1成为朋友的所有用户,第二个联接会进一步将其限制为同时也是@user_id2的朋友的用户。

此查询的执行速度比使用子查询的速度快得多。如果zebra表在两个方向上存储了友谊,则查询会更快,从而可以更好地利用表索引,并且可以删除OR部分ON条款:

SELECT u.username, u.user_colour, u.username_clean, u.user_avatar, u.user_avatar_type 
FROM users u
JOIN zebra z1 ON u.user_id = z1.user_id AND z1.friend=1 AND z1.zebra_id = @user_id1
JOIN zebra z2 ON u.user_id = z2.user_id AND z2.friend=1 AND z2.zebra_id = @user_id2
ORDER BY u.username_clean ASC