使用 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
我加入了两个 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