SQL 语句包含在相关子查询中没有匹配项的行
我有下面的相关子查询。 table1中的每个id(147,148,149)在table2中都有很多记录。然而,id 148 没有与语句中的时间条件匹配的记录。因此它不包含在输出中。我希望在计数列中包含 0。需要改变什么?
SELECT b.fkid, COUNT(DISTINCT username)
FROM table2 AS b
WHERE
b.fkid IN ( 147,148,149 )
AND time > (SELECT SUBTIME(a.endTime, SEC_TO_TIME( 60*60 )) FROM table1 AS a WHERE a.id = b.fkid)
GROUP BY b.fkid
该语句返回:
b.fkid COUNT(DISTINCT username)
147 41
149 26
我希望它返回:
b.fkid COUNT(DISTINCT username)
147 41
148 0
149 26
好的,我找到了解决方案。这是 rexem 答案的修改版本:
SELECT t.fkid,
IFNULL(nu.num_users, 0)
FROM TABLE_2 t
LEFT JOIN (SELECT t.fkid,
COUNT(DISTINCT t.username) 'num_users'
FROM TABLE_2 t
JOIN TABLE_1 a ON a.id = t.fkid
AND SUBTIME(a.endTime, SEC_TO_TIME( 60*60 )) < t.time
GROUP BY t.fkid) nu ON nu.fkid = t.fkid
WHERE t.fkid IN (147, 148, 149)
GROUP BY t.fkid, nu.num_users
Changes from rexem's answer:
"SEC_TO_TIME( 60*60 )) = t.time" to "SEC_TO_TIME( 60*60 )) < t.time"
Removed "t.time" in GROUP BY clause of subquery
I have the correlated subquery below. Each id (147,148,149) in table1 has many records in table2. The id 148 however has no records that match the time condition in the statement. Therefore it is not included in the output. I want it to be included with a 0 for the count column. What needs to be changed?
SELECT b.fkid, COUNT(DISTINCT username)
FROM table2 AS b
WHERE
b.fkid IN ( 147,148,149 )
AND time > (SELECT SUBTIME(a.endTime, SEC_TO_TIME( 60*60 )) FROM table1 AS a WHERE a.id = b.fkid)
GROUP BY b.fkid
This statement returns:
b.fkid COUNT(DISTINCT username)
147 41
149 26
I want it to return:
b.fkid COUNT(DISTINCT username)
147 41
148 0
149 26
Okay I got the solution. It is a modified version of rexem's answer:
SELECT t.fkid,
IFNULL(nu.num_users, 0)
FROM TABLE_2 t
LEFT JOIN (SELECT t.fkid,
COUNT(DISTINCT t.username) 'num_users'
FROM TABLE_2 t
JOIN TABLE_1 a ON a.id = t.fkid
AND SUBTIME(a.endTime, SEC_TO_TIME( 60*60 )) < t.time
GROUP BY t.fkid) nu ON nu.fkid = t.fkid
WHERE t.fkid IN (147, 148, 149)
GROUP BY t.fkid, nu.num_users
Changes from rexem's answer:
"SEC_TO_TIME( 60*60 )) = t.time" to "SEC_TO_TIME( 60*60 )) < t.time"
Removed "t.time" in GROUP BY clause of subquery
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
尝试:
Try:
尝试使用 COALESCE 来处理时间与空集进行比较的场景(例如,因为 table1 和 table2 之间没有匹配项):
COALESCE 接受一组无限制的参数,并且从该组中返回第一个非空参数。
Try using COALESCE to handle the scenarios where time is compared to the empty set (e.g., because there are no matches between table1 and table2):
COALESCE takes an unbounded set of parameters and, from this group, will return the first non-null parameter.
无论如何,这有帮助吗?
编辑:我不确定这是否可以在 mysql 中工作。但是,我希望您了解使用它来构建查询。
Does this help in anyway?
EDIT: I am not sure if this can work in mysql. But, I hope you get the idea to build the query using this.
我认为将零带入结果的最佳机会是使用(不相交的)UNION。第一部分是您当前的查询;第二个子句将查找没有相关条目的值,并为计数列选择常量 0。
通常,外连接就可以解决问题。这里的困难在于外连接会产生 ID = 148 的一行数据,因此 COUNT 会给出结果 1,而不是 0。
I think your best chance of getting the zero into the result is using a (disjoint) UNION. The first part would be your current query; the second clause would find the values where there are no relevant entries, selecting the constant 0 for the count column.
Often, an outer join would do the trick. The difficulty here is that the outer join would produce a row of data for ID = 148, and therefore COUNT would give an answer of 1, not 0.