基本上我想要一个列,如果为null则返回0。我在嵌套语句中使用ifnull,当我自己运行嵌套语句时,列返回0,但是当我运行整个查询时,我再次得到NULL。这是我的代码:
SELECT Text, Verbo, Objeto, mPosts FROM Posts
LEFT JOIN (SELECT ID, IFNULL(COUNT(*),0) AS mPosts FROM `Posts` WHERE Date >= DATE_ADD(CURDATE(), INTERVAL -30 DAY) GROUP BY `Verbo`,`Objeto`) AS B ON Posts.ID = B.ID
我可以将IFNULL移动到主要的选择语句,但我宁愿不这样做:
SELECT Text, Verbo, Objeto, IFNULL(mPosts,0) FROM Posts
LEFT JOIN (SELECT ID, COUNT(*) AS mPosts FROM `Posts` WHERE Date >= DATE_ADD(CURDATE(), INTERVAL -30 DAY) GROUP BY `Verbo`,`Objeto`) AS B ON Posts.ID = B.ID
为什么我不能在嵌套语句中执行此操作?它可以以任何其他方式完成,以便我不必在主查询中使用它吗?
答案 0 :(得分:1)
如果您NULL
收到IFNULL(COUNT(*),0)
,那是因为LEFT JOIN
与ON
的{{1}}条款不匹配,所以右表中的所有值均为Posts.ID = B.ID
。
是的,您需要将NULL
移至顶级IFNULL
子句。
答案 1 :(得分:0)
您必须在外部查询中拥有IFNULL
。
内部查询中的COUNT(*)
没有返回NULL,当左侧的行没有来自右侧行源的匹配行时,LEFT JOIN操作正在创建NULL侧。
此查询与您的查询相同:
SELECT a.Text
, a.Verbo
, a.Objeto
, c.mPosts
FROM `Posts` a
LEFT
JOIN ( SELECT b.ID
, COUNT(*) AS mPosts
FROM `Posts` b
WHERE b.Date >= DATE_ADD(CURDATE(), INTERVAL -30 DAY)
GROUP BY b.`Verbo`, b.`Objeto`
) c
ON c.ID = a.ID
重新格式化的查询可以更明显地解决问题所在。
您的内联视图(子查询)正在两列上执行GROUP
BY,然后从每个计数值中包含的某一行返回ID
的值。
(其他关系数据库会在这个语句中抛出“非聚合在选择列表中,不在分组中”类型异常,其中MySQL更自由,这既方便又诅咒。)
查询返回的结果集很奇怪。目前还不清楚你想要在这里返回什么结果集。
“count”子查询中的行将与每个COUNT()值中包含的一行匹配。 (只要COUNT(*)大于1,外部查询中就会有一行没有来自内联视图的匹配行... GROUP BY正在折叠所有的ID值包含的行只包含一行中包含的某个ID值。
我毫不犹豫地提出任何建议,因为我不清楚你想要归还什么。
你可以做的一件事是从WHERE子句中删除谓词,而是在聚合中检查这个条件,就像这样......
SELECT a.`Text`
, a.`Verbo`
, a.`Objeto`
, c.`mPosts`
FROM `Posts` a
LEFT
JOIN ( SELECT b.ID
, SUM(IF b.`Date` >= DATE_ADD(CURDATE(), INTERVAL -30 DAY)) AS `mPosts`
FROM `Posts` b
GROUP BY b.`Verbo`, b.`Objeto`
) c
ON c.ID = a.ID
这可能会减少NULL值的数量,但是它没有解决LEFT JOIN的更基本的问题,左边的任何一行都没有从右侧产生匹配,从而产生NULL。