2013-08-30 18 views
0

我怎么会做以下MySQL中:MySQL的选取中没有匹配连接

我有3个表:

用户:ID

通信:ID,CREATION_DATE

user_communication:user_id,communication_id

现在我想选择自给定日期以来已有通信的所有用户。

以下是我现在所拥有的,但我坚持如何得到我上面描述的。

SELECT DISTINCT u.id FROM user u 
LEFT JOIN user_communication uc ON uc.user_id = u.id 
LEFT JOIN communication c ON c.id = uc.communication_id 
WHERE c.creation_date < '2013-8-1'; 

回答

3

where条件是取消left join。最初的解决办法是将其移动到on条款:

SELECT DISTINCT u.id FROM user u 
LEFT JOIN user_communication uc ON uc.user_id = u.id 
LEFT JOIN communication c ON c.id = uc.communication_id and c.creation_date < '2013-8-1'; 

但是,这你想要什么没有做。这将检索所有记录。如果在select子句中有创建日期字段,则在该日期之前有记录时它将为NULL。

对于自该日起没有沟通,你可以做一个“双”负”查询寻找那些自该日起的记录,并返回不匹配:

SELECT DISTINCT u.id 
FROM user u LEFT JOIN 
    user_communication uc 
    ON uc.user_id = u.id LEFT JOIN 
    communication c 
    ON c.id = uc.communication_id and c.creation_date >= '2013-08-01' 
WHERE c.creation_date is NULL; 

编辑:

我这个问题比我上面的答案稍微微妙一点,每个用户都有多个通信,所以以后的查询都会通过u.id分组来测试,然后检查上面的连接没有非NULL值:

SELECT u.id 
FROM user u LEFT JOIN 
    user_communication uc 
    ON uc.user_id = u.id LEFT JOIN 
    communication c 
    ON c.id = uc.communication_id and c.creation_date >= '2012-08-01' 
group by u.id 
having min(c.creation_date is null) = 1; 
+0

纠正所有罪状 – Strawberry

+0

可能比我提供一个更好的解决方案。 – Taemyr

+0

嗯我现在正在测试,但它不适合我。我做了一个sqlfiddle来显示它,它不应该返回用户1,但仍然会:http://sqlfiddle.com/#!2/9be37/1 –

1
SELECT DISTINCT u.id FROM user u 
LEFT JOIN user_communication uc ON uc.user_id = u.id 
LEFT JOIN (SELECT * FROM communication WHERE creation_date < '2013-8-1') c 
ON c.id = uc.communication_id 
WHERE c.id is NULL; 
0

一些研究和帮助后,我有以下查询,这似乎工作:

SELECT DISTINCT(u.id) 
FROM user u 
WHERE (SELECT coalesce(max(c.creation_date), '1900-01-01 00:00:00') last_creation_date 
     FROM user inneru 
     LEFT JOIN user_communication uc ON uc.user_id = inneru.id 
     LEFT JOIN communication c ON c.id = uc.communication_id 
     WHERE inneru.id = u.id) < '2012-08-01' 

SQLFiddle:http://sqlfiddle.com/#!2/5dfad/10

相关问题