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

条件を句から句にItem移動します。を次のように変更します。WHEREONCOUNT(*)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 ;

これを記述する一般的な方法が少なくとも 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 ;
于 2013-04-18T15:46:28.043 に答える