0

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

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

如何修改以下查询,为给定的 Area.cityId 选择所有区域 - 并简单地计算“recentItems”= 0,对于没有最近项目的区域(即不匹配对项目的限制。在过去 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
4

2 回答 2

1

将条件 aboutItemWHERE子句移动到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.nameSELECTandORDER 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 ;
于 2013-04-18T15:46:28.043 回答
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
于 2013-04-18T16:04:21.023 回答