如果未找到连接结果,请选择COUNT(*)零

时间:2013-04-18 15:40:14

标签: mysql

我正在尝试为给定的城市ID选择所有区域。 另外,我正在计算COUNT(*)以查看每个区域存在多少个项目。 由于Items通过manyToMany关系与Areas相关,因此JOIN必须通过名为Item_Area的相应JOIN表进行。

不幸的是,我只获得了实际拥有近期物品的区域 - 但我想要所有区域。如果没有,最近的项目应该简单为零。我认为问题与发布日期的WHERE条件有关 - 但我无法弄清楚如何使其正常工作。

如何修改以下查询,为给定的Area.cityId选择所有区域 - 并简单地计算“recentItems”= 0,对于没有最近项目的区域(即不匹配)对Item.published字段的限制是在过去10天内。

SELECT
  `Area`.`id`, `Area`.`name`, COUNT(*) AS `recentItems`
  FROM `Area`
  LEFT JOIN `Item_Area` ON `Area`.`id` = `Item_Area`.`areaId`
  LEFT JOIN `Item` ON `Item`.`id` = `Item_Area`.`itemId`
WHERE
  `Area`.`cityId` = "1" AND
  Item.published > DATE_SUB(NOW(), INTERVAL 10 DAY) GROUP BY `Area`.`id`
ORDER BY `Area`.`name` ASC

2 个答案:

答案 0 :(得分:1)

Item子句中的WHERE条件移至ON子句。并将COUNT(*)更改为COUNT(Item.id)

SELECT
  Area.id, Area.name, COUNT(Item.id) AS recentItems
FROM Area
  LEFT JOIN Item_Area ON Area.id = Item_Area.areaId
  LEFT JOIN Item ON  Item.id = Item_Area.itemId
                 AND Item.published > DATE_SUB(NOW(), INTERVAL 10 DAY) 
WHERE
  Area.cityId = '1' 
GROUP BY 
  Area.id
ORDER BY 
  Area.name ASC ;

请注意,上述内容不会在某些(严格)设置下运行,因为Area.nameSELECT列表中的ORDER BY不在GROUP BY名单。这取决于sql_mode是否已设置为 ONLY_FULL_GROUP_BY 。因此,将该组更改为:

可能更明智
GROUP BY 
  Area.id, Area.name

你也可以使用别名,使代码更具可读性(至少对很多人来说):

SELECT
  a.id, a.name, COUNT(i.id) AS recentItems
FROM 
    Area AS a
  LEFT JOIN 
    Item_Area AS ia ON a.id = ia.areaId
  LEFT JOIN 
    Item AS i ON  i.id = ia.itemId
              AND i.published > DATE_SUB(NOW(), INTERVAL 10 DAY) 
WHERE
  a.cityId = '1' 
GROUP BY 
  a.id
ORDER BY 
  a.name ASC ;

至少有两种常见的方式来编写它。首先在派生表中进行分组,然后加入:

SELECT
  a.id, a.name, COALESCE(g.recentItems, 0) AS recentItems
FROM 
    Area AS a
  LEFT JOIN 
    ( SELECT 
        ia.areaId, COUNT(*) AS recentItems
      FROM 
          Item_Area AS ia 
        JOIN 
          Item AS i ON  i.id = ia.itemId
      WHERE 
        i.published > DATE_SUB(NOW(), INTERVAL 10 DAY)
      GROUP BY
        ia.areaId
    ) AS g ON a.id = g.areaId
WHERE
  a.cityId = '1' 
ORDER BY 
  a.name ASC ;

或使用内联子查询:

SELECT
  a.id, a.name, 
  COALESCE( 
      ( SELECT 
          COUNT(*)
        FROM 
            Item_Area AS ia 
          JOIN 
            Item AS i ON  i.id = ia.itemId
        WHERE 
          i.published > DATE_SUB(NOW(), INTERVAL 10 DAY)
          AND
          a.id = ia.areaId
      ), 0
          ) AS recentItems
FROM 
    Area AS a
WHERE
  a.cityId = '1' 
ORDER BY 
  a.name ASC ;

答案 1 :(得分:0)

Item.published上的过滤条件限制数据可用于具有项目条目的区域。由于您需要没有项目的区域,您需要插入条件Item.published> DATE_SUB(NOW(),INTERVAL 10 DAY)加入。

SELECT
  `Area`.`id`, `Area`.`name`, COUNT(1) AS `recentItems`
FROM `Area`
LEFT JOIN `Item_Area` ON `Area`.`id` = `Item_Area`.`areaId`
LEFT JOIN `Item` ON `Item`.`id` = `Item_Area`.`itemId` and 
WHERE
 `Area`.`cityId` = "1" 
 GROUP BY `Area`.`id`
 ORDER BY `Area`.`name` ASC