【问题标题】:Get average rating for individual shop using mysql使用mysql获取单个商店的平均评分
【发布时间】:2021-02-15 02:29:48
【问题描述】:

我正在加入两个表,即带有评级表的商店表,并且想要获取所有带有单个商店评级的商店列表,我已经为此编写了查询,但在输出中只获取那些在评级表中具有评级的商店,但我想要如果店铺没有评分则显示 0 否则按表记录显示。

车间表:-

id  shop name      
  1     shop_1      
  2     shop_2      
  3     shop_3      
  4     shop_4

评分表

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 

【问题讨论】:

  • @Strawberry 都说的很清楚了,还有什么要说的吗?
  • 如果我必须解释链接,这反而会破坏提供链接的意义,不是吗?
  • 我没有创建任何小提琴链接,正在处理项目所以现在面临这个问题。
  • 试试这个 SELECT shop.id , shop.name FROM shop LEFT JOIN rating_reviews ON shop.id=rating_reviews.shop_id

标签: php mysql sql codeigniter join


【解决方案1】:

我想建议另一种方法,完全避免加入:

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

【讨论】:

  • @msp 更新了我的查询。对此感到抱歉。干杯!
  • 谢谢,它按预期工作,但我有点怀疑为什么我们不能使用 join。
【解决方案2】:

聚合函数

您遇到错误的原因是像 AVG | COUNT 这样的函数是聚合函数,也就是说它们聚合所有数据并通常输出一条记录/结果。

例如:

  • 假设您有一个表 shops,其中 id 作为主键
  • 桌子上有35家店铺
  • 主键中没有中断(例如,它从 1 变为 35)

然后以下查询将返回 1 行/结果:

# 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

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

您的查询函数遵循相同的原则,例如 COUNT AVG 函数是一个聚合函数,将从查询返回 1 结果/行。

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

【讨论】:

  • 我故意不使用 group by,因为完整的 group by 在实时服务器中造成问题并且无权启用它。
  • @msp 抱歉,您无权启用GROUP BY
猜你喜欢
  • 1970-01-01
  • 2013-02-06
  • 1970-01-01
  • 1970-01-01
  • 2021-03-28
  • 1970-01-01
  • 2019-08-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多