在mysql中组合联接的语法

时间:2010-04-25 01:08:13

标签: sql mysql

我似乎记得在某处读取有一种方法可以将LEFT JOIN语句组合成一个更简单的查询。我有以下查询,并希望有人可以好好看看它。

SET @userId = 8;

SELECT ug.user_id, COUNT(DISTINCT goal_id) as matches
FROM user_goal ug, user u, profile p
LEFT JOIN user_block ub ON @userId = ub.blocked_id
LEFT JOIN user_block ub2 ON @userId = ub2.blocker_id
LEFT JOIN user_user uu ON @userId = uu.user_id
LEFT JOIN friend_request fr ON @userId = fr.user_id
WHERE ug.user_id = u.id AND u.profile_id = p.id
AND (ub.blocker_id IS NULL OR ub.blocker_id != ug.user_id)
AND (ub2.blocked_id IS NULL OR ub2.blocked_id != ug.user_id)
AND (uu.user_friends_id IS NULL OR uu.user_friends_id != ug.user_id)
AND (fr.to_user_id IS NULL OR (fr.to_user_id != ug.user_id))
AND ug.user_id!=@userId
AND p.suggestible
AND goal_id IN (SELECT iug.goal_id FROM user_goal iug WHERE user_id=@userId)
GROUP BY user_id ORDER BY matches DESC LIMIT 4

1 个答案:

答案 0 :(得分:4)

您可以通过删除@userId来开始改进此整体查询;)您可以引用前面提到的列来维护该连接。

这可能会导致子查询出现问题;这不需要在那里。该子查询几乎肯定会导致查询执行缓慢。您可以将子查询合并到您也要加入的派生表中(因为它使用相同的user_id),这样它只执行一次,而不是像现在一样对结果集中的每个记录执行一次。

SELECT
  ug.user_id,
  COUNT(DISTINCT goal_id) as matches
FROM
  user_goal ug
  INNER JOIN user u ON ug.user_id = u.id
  INNER JOIN profile p ON u.profile_id = p.id
  LEFT JOIN user_block ub ON u.id = ub.blocked_id
  LEFT JOIN user_block ub2 ON u.id = ub2.blocker_id
  LEFT JOIN user_user uu ON u.id = uu.user_id
  LEFT JOIN friend_request fr ON u.id = fr.user_id
  LEFT JOIN (
    SELECT iug.goal_id FROM user_goal
  ) iug ON iug.user_id = u.id
WHERE
  /* I looked at your WHERE clause for a while and couldn't get my head
     around what you're trying to do so I'll leave this to you */

将子查询直接放入JOIN并命名它会创建一个派生表,真正加快速度(并整理恕我直言)。