使用 mysql 获取单个商店的平均评分

Get average rating for individual shop using mysql

我加入了两个 table,即评分为 table 的商店 table 并希望获取所有具有个别商店评分的商店列表,我已经对此进行了书面查询,但在输出中得到只有那些在评分 table 中有评分的商店,但我想如果商店没有评分则显示 0,否则按照 table 记录显示。

店铺table:-

id  shop name      
  1     shop_1      
  2     shop_2      
  3     shop_3      
  4     shop_4

评分table

id  shop_id  rating      
  1     1      3      
  2     4      2

查询:

$this->db->select('shop.*,shop.id as shop_id');
    $this->db->select('COALESCE(ROUND(AVG(rat.rating),1),0) as avgRate');
    $this->db->from('shop');
    $this->db->join('rating_reviews as rat', 'rat.shop=shop.id', 'left');
    $this->db->get()->result_array();

当前输出:

  id  shop_id      avgRate       
   1     1            3      
   2     4            2 

预期输出:

 id  shop_id      avgRate     
   1     1            3     
   2     2            0           //(no rating given for this shop)    
   3     3            0           //(no rating given for this shop)       
   4     4            2 

聚合函数

你 运行 出错的原因是像 AVG | COUNT 这样的函数是 聚合函数 也就是说它们聚合了所有数据和 通常 输出单个 record/result.

例如:

  • 假设您有一个 table shops,其中 id 作为主键
  • table
  • 中有 35 家商店
  • 主键没有中断(例如从 1 到 35)

下面的查询将 return 1 row/result:

# Query                          # Output:  # FIELD_1 # FIELD_2 (second statement)
SELECT COUNT(shop.id) FROM shop             # 35
SELECT shop.id, COUNT(shop.id) FROM shop    # 1       # 35

以上两个语句都会 return 1 结果。第一个只是商店数量的 count (35),第二个会额外输出第一家商店的 id (1)。

您的查询 函数基于相同的原理,例如 COUNT AVG 函数是一个聚合函数,将 return 1 result/row 来自查询。

SELECT 
    shop.*, shop.id as shop_id,
    COALESCE(ROUND(AVG(rat.rating),1),0) as avgRate
FROM shop
    LEFT JOIN rating_reviews AS rat ON rat.shop=shop.id

-- Outputs: All fields from `shop` for the first shop followed by [shop_id] and [avgRate]
-- For example...
# shop.id # shop.name # shop.type   # shop_id # avgRate
# 1       # Tesco     # Supermarket # 1       # 3.5

但是有两种方法可以避免这种行为:

使用GROUP BY

SELECT i, AVG(...) AS a FROM ... LEFT JOIN ... GROUP BY i

嵌套 SELECT 语句

SELECT i, (SELECT AVG(...) FROM ... WHERE ...) AS a FROM ...

分组依据

SELECT 
    shop.*, shop.id as shop_id,
    COALESCE(ROUND(AVG(rat.rating),1),0) as avgRate
FROM shop
    LEFT JOIN rating_reviews AS rat ON rat.shop=shop.id
GROUP BY shop.id

嵌套选择

SELECT
    shop.*, shop.id as shop_id,
    (SELECT
         COALESCE(ROUND(AVG(rat.rating),1),0)
     FROM rating_reviews as rat
     WHERE rat.shop=shop.id
    ) as avgRate
FROM shop

我想建议另一种方法,完全避免连接:

select
  distinct id,
  (
     select coalesce(round(avg(rat.rating), 1), 0)
     from rating_reviews as rat where shop.id=rat.shop
  ) as avgRate
from shop