来自查询的奇怪行为

时间:2015-12-15 15:35:55

标签: mysql sql tsql mysqli

我似乎无法弄清楚为什么只有当john低于a时此查询才有效。

聊天表

**chatid**      **username**
   132              john

测试表

**chatid**       **username**
   132               john
   132               a

查询

CREATE TEMPORARY TABLE tmp ( ids INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,id Int NOT NULL);
INSERT INTO tmp (id) VALUES (132);
SELECT  i.id, IFNULL(COUNT(ta.chatid),0), count(l.chatid),IFNULL(x.username, '@')
FROM tmp i 
inner JOIN chat ta ON ta.chatid = i.id
left JOIN test l ON ta.chatid = l.chatid
left  JOIN chat x ON (x.chatid = l.chatid and x.username = l.username)

GROUP BY i.id
ORDER BY i.ids asc;

聊天测试表是一对多的关系。查询只能根据测试表的顺序正常工作。例如,如果john低于a,它将显示正确的john。但是,如果john高于a,则查询会导致null用户名不正确(仍应显示john)。

目标:我尝试只显示x.username,如果他在聊天和测试表中都存在,否则显示为null(@)。我需要这个工作而不会搞乱select语句中的计数

非常感谢任何帮助

1 个答案:

答案 0 :(得分:1)

你是外连接x,所以对于某些记录,可能会填充x.username,对于某些记录,它可能为null。您按i.id分组并选择x.username。但是对于一个id,可以有许多用户名,甚至是NULL,如示例中所示。你没有告诉DBMS你想要哪一个(例如字母表中的最后一个用户名),所以DBMS任意选择一个。在你的情况下为NULL。运气不好,但是你把它留给了机会,所以不要抱怨; - )

我不知道你想要达到什么目标。您的示例太小,我无法准确理解查询应该执行的操作。但无论如何,在聚合时,告诉DBMS要选择哪个值。 IFNULL(MIN(x.username), '@')可以在这里解决问题(但我无法判断查询是否完全符合您的要求)。

这就是你所追求的:计算测试中chatid的所有出现次数并仅在测试记录中存在时显示用户名?

select 
  c.chatid, 
  count(t.chatid),
  case when max(t.username = c.username) then c.username else '@' end
from chat c 
left join test t on t.chatid = c.chatid
where c.chatid in (select id from tmp)
group by c.chatid;