基于另一个表中存在条件的条件选择值?

时间:2019-04-25 13:50:15

标签: mysql sql

我有一个用户表和一个表,该表跟踪线程以及每个线程中涉及的用户。我试图制作一个SELECT语句,使我可以查看任何线程,并获取完整的用户列表以及其中是否包含用户的列。最初且天真地,我使用以下内容开始:

SELECT 
listusers.idx as Value,
CONCAT(FirstName, ' ', LastName) as Label,
False as selected
FROM
listUsers
WHERE 
listusers.customerId = 0

这使我回到了所有用户手中,这时我以编程方式查看了另一个表并手动打开了该表中的用户。

我通过查询尝试执行以下操作-

SELECT l.idx as Value,
CONCAT(FirstName, ' ', LastName) as Label,
IF(h.userId IS NULL,False, True) as Selected
FROM listusers l
LEFT JOIN helpmessageparticipants h ON l.idx = h.userId
WHERE l.customerId = 0 AND 
h.parentThreadId={Root Container.threadId})

但是由于某些原因,只会返回被选择的用户。如果只有3个用户在线程中,那么我只能找回这3个用户,并且所有用户都是所选的True。我想要的最终结果是始终取回所有用户(l.customerId = 0的用户)以及关于某个线程的helpmessageparticipant中是否存在它们的真值列或假布尔值列的附加列。我的第二个查询出了什么问题?

我正在使用MySQL 5.6。

2 个答案:

答案 0 :(得分:2)

您需要移动

h.parentThreadId={Root Container.threadId})

条件从WHERE子句进入联接条件,否则将您的LEFT JOIN转换为INNER JOIN

SELECT l.idx as Value,
CONCAT(FirstName, ' ', LastName) as Label,
IF(h.userId IS NULL,False, True) as Selected
FROM listusers l
LEFT JOIN helpmessageparticipants h ON l.idx = h.userId AND 
       h.parentThreadId={Root Container.threadId})
WHERE l.customerId = 0

这在'Outer Join Optimization'下的手册中进行了讨论:

  

对于LEFT JOIN,如果对于所生成的NULL行,WHERE条件始终为false,则将LEFT JOIN更改为内部联接

在您的示例中,对于生成的NULL行,h.parentThreadId={Root Container.threadId})将为false,因此查询将更改为INNER JOIN,而您只会取回所选的用户。

答案 1 :(得分:0)

如Nick所指出的,LEFT JOIN版本要求该条件位于ON子句中,而不是WHERE子句中。我将其写为:

SELECT l.idx as Value,
       CONCAT(FirstName, ' ', LastName) as Label,
       (h.userId IS NOT NULL) as Selected
FROM listusers l LEFT JOIN
     helpmessageparticipants h
     ON l.idx = h.userId AND 
        h.parentThreadId = {Root Container.threadId})
WHERE l.customerId = 0;

但是,这假设h中只有一个匹配项-否则您将获得重复的行。对于单个线程,这可能不是问题。但是您可能还有其他允许多个匹配项的过滤条件。因此,我认为exists子句可能更合适。

SELECT l.idx as Value,
       CONCAT(FirstName, ' ', LastName) as Label,
       (EXISTS (SELECT 1
                FROM helpmessageparticipants h
                WHERE l.idx = h.userId AND 
                      h.parentThreadId = {Root Container.threadId}
              )
       ) as Selected
FROM listusers l LEFT JOIN

WHERE l.customerId = 0;