0

基本上我希望一列在 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 语句,但我不希望:

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

为什么我不能在嵌套语句上做到这一点?可以以其他任何方式完成,以便我不必在主查询中使用它吗?

4

2 回答 2

1

如果您正在获取NULLfor IFNULL(COUNT(*),0),那是因为 theLEFT JOIN与您的ON子句 of不匹配Posts.ID = B.ID,因此右表中的所有值都将是NULL

所以是的,您需要转到IFNULL顶级SELECT子句。

于 2012-09-13T17:48:47.560 回答
0

您必须IFNULL在外部查询上有。

内部COUNT(*)查询中没有返回 NULL,NULL 是由 LEFT JOIN 操作创建的,当左侧的行没有来自右侧行源的匹配行时。

此查询等效于您的查询:

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

重新格式化的查询使问题所在的位置更加明显。

您的内联视图(子查询)正在对两列执行GROUPBY,然后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 的更基本问题。

于 2012-09-13T18:23:29.373 回答