2016-11-15 174 views
1

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

(请注意,我需要保持限制与形式传入变量状态的项目在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' 
+0

created_by会比updated_by更新吗? – Uueerdo

+0

在SELECT子句中使用ON子句中的相同CASE语句。 –

+0

@Uueerdo包含所有的任务,是创建的项目可以比新的更新,因为新的项目会经常进行。对于单个任务,更新的时间戳总是比创建的更新。 – seibzehn

回答

1

您可以模拟很多的“如果”与或逻辑和而像这样:

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) 

,或者使用类似的逻辑是什么,你有选择:

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

或者(因为OR和上面的更复杂的比较几乎排除了索引的任何好处),您可以连接到users表两次并选择优先值E在选择:

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和额外的加入会不会引起歧义。

+0

如果'updated_by'可能为NULL,则可能需要使用LEFT JOIN作为“更新用户”。 –

+0

@PaulSpiegel啊,很好,我只是在第一遍时做了一个快速切割/粘贴/重新别名。 – Uueerdo

+1

有了适当的索引,join-twice-solution应该是最快的。另外,如果'created_at'永远不会比'updatet_at'更早,你可以选择'tasks.updated_at AS recent_profile_pic'。如果'updated_by'全部为NULL,当没有提交时,可以选择'COALESCE(uu.profile_pic,cu.profile_pic)'。这会使代码看起来不那么复杂。 –