使用此SQL查询使用INNER JOIN和ON防止重复

时间:2016-11-15 23:48:27

标签: php mysql pdo

请参考下面的SQL查询。我正在尝试创建一个简单的活动供稿,该供稿将与任务表中的updated_by和/或created_by字段(以较新者为准)中记录的人员匹配,并在用户中显示其个人资料图片表。这个查询有效,但是当两个字段具有不同的用户时我得到重复,因为在ON子句中,OR语句的两个元素都将返回true,因为总有一个created_by将匹配users表中的某个人 - 我不能弄清楚当两个字段都填充不同的用户时,如何将其限制为一个。我已经尝试向ON子句添加更多CASE WHEN,但是没有if / else逻辑,所以它只是默认为两次都是true并返回相同的结果。

(注意,我需要保持在WHERE子句中限制结果的能力,其中状态项作为变量传入,查询包含在PHP函数中。)

想法?

SELECT tasks.*, users.profile_pic, 
CASE WHEN tasks.updated_at > tasks.created_at 
THEN tasks.updated_at 
ELSE tasks.created_at 
END AS recent_activity 
FROM tasks 
INNER JOIN users 
ON tasks.updated_by = users.name OR tasks.created_by = users.name 
WHERE status <> :status1 AND status <> :status2 
ORDER BY recent_activity DESC LIMIT 10'

1 个答案:

答案 0 :(得分:1)

您可以使用OR和AND模拟许多“if”逻辑,如下所示:

ON (tasks.updated_at > tasks.created_at AND tasks.updated_by = users.name)
   OR (tasks.updated_at <= tasks.created_at AND tasks.created_by = users.name)

或使用类似于select中的逻辑:

ON CASE 
      WHEN tasks.updated_at > tasks.created_at 
      THEN tasks.updated_by 
      ELSE tasks.created_by
      END = users.name

或者(因为OR和更复杂的比较,比如上面几乎排除了索引的任何好处),你可以加入users表两次并在select中选择优先级值:

SELECT tasks.*
  , CASE WHEN tasks.updated_at > tasks.created_at 
    THEN uu.profile_pic
    ELSE cu.profile_pic
  END AS recent_profile_pic 
  , CASE WHEN tasks.updated_at > tasks.created_at 
    THEN uu.name 
    ELSE cu.name 
  END AS recent_activity 
FROM tasks
LEFT JOIN users AS uu ON tasks.updated_by = uu.name 
INNER JOIN users AS cu ON tasks.created_by = cu.name 
WHERE status <> :status1 AND status <> :status2 
ORDER BY recent_activity DESC LIMIT 10

这假设您使用的所有字段都没有指定它们所属的表格来自tasks,额外的连接不会导致含糊不清。