条件を句から句に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.name
にSELECT
および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 ;
これを記述する一般的な方法が少なくとも 2 つあります。最初に派生テーブルでグループ化し、次に結合します。
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 ;