如何重写 ON 子句以避免使用 OR

How to rewrite ON clause to avoid using OR

我有一个非常低效的查询,因为在 JOIN.

中使用 OR 作为 ON 语句的一部分
SELECT Meetings.SomeFields, Organisations.SomeFields,
FROM Meetings
     LEFT JOIN Users
          ON (Meetings.AdministratorID = Users.UserID
              OR Meetings.ChairpersonID = Users.UserID)
     LEFT JOIN Organisations
          ON Organisations.OrganisationID = Users.OrganisationID;

(注意:这是对问题的稍微简化。实际上,这是一个包含大约 20 个表的复杂查询,但我已将性能问题减少到查询。)

这试图实现以下加入组织的逻辑:如果有主席,则应使用主席的组织。否则,应使用管理员的组织。这些字段中的一个或两个都将被填充,随后的 WHERE 子句确保输出中不包含无关的记录(例如,两个都被填充的地方)。

Using EXPLAIN 我可以看到 OR 运算符意味着不能使用索引并且需要单独检查所有行组合。约 10 万个会议记录和约 7 万个用户记录,这会产生巨大的查询性能问题,因为这意味着需要检查约 70 亿个组合。

删除表达式的 OR Meetings.ChairpersonID = Users.UserID 部分会立即得到结果,因为查询可以正确使用索引,但显然不会给出我们需要的结果。

任何人都可以建议一种重写此查询以避免性能问题的方法吗?

我正在使用 MySQL 5.

尝试使用 exists:

SELECT COUNT(*)
FROM Meetings m
WHERE EXISTS (SELECT 1
              FROM Users u
              WHERE u.UserID = m.AdministratorID
             ) OR
      EXISTS (SELECT 1
              FROM Users u
              WHERE u.UserID = m.ChairpersonID
             );

这可以利用 Users(UserId) 上的索引——如果 UserId 是主键,它会自动存在。

注意:我认为这可以通过计算 会议 来满足您的需求。您的版本计算用户。因此,如果给定会议的主席和管理员都在 Users,那么这将计为 2 个用户,而不是 1 个会议。

If there is a chairperson, then the chairperson's organisation should be used. Otherwise, the administrator's organisation should be used.

"If... otherwise..."不是OR,是蕴涵,可以通过COALESCE简洁地表达:

SELECT Meetings.SomeFields, Organisations.SomeFields,
FROM Meetings
     LEFT JOIN Users
          ON COALESCE(Meetings.ChairpersonID, Meetings.AdministratorID) = Users.UserID
     LEFT JOIN Organisations
          ON Organisations.OrganisationID = Users.OrganisationID;

这样,对于每个 Meetings 行,可以通过查找 Users PK 找到对应的 Users 行。


还有一件事...如果 ChairpersonIDAdministratorID 不能 both 为 NULL,那么你可以内连接到 Users .