我有一张包含以下表格的数据库:
ads
ads_rating
ads_province
ads_promo
etc...
我生成了一个复杂的查询,因为我需要某些广告,每个广告的平均评分为。
在ads_rating表中我有和id,rating,user_id,date_rated
如何加入广告。*表并添加一个名为" rating_average"的新字段。或类似的东西。
我想我必须在JOIN中创建一个SELECT,但我是MySQL的新手。
这是我的实际功能查询:
SELECT
category.id AS category_id,
category.subcat AS category_name,
category.`desc` AS category_desc,
category.`name` AS category_pretty_name,
ads.id,
ads.header,
ads.price,
ads.oldprice,
ads.sellfast,
ads.`hash`,
ads.foto1,
ads.foto2,
ads.foto3,
ads.foto4,
ads.foto5,
ads.user_id,
SUBSTR(ads.body, 1, 160) AS body,
ads.subcat_id,
ads.updated,
ads.created,
ads.email,
ads.`name`,
ads.phone,
ads.hits,
ads.hidden,
promo.promotype AS promo_type,
supercategory.`name` AS supercategory_name,
supercategory.id AS supercategory_id,
ads_rating.rating,
promo.ads_id
FROM `ads`
JOIN `category` ON `category`.`id` = `ads`.`subcat_id`
JOIN `supercategory` ON `supercategory`.`id` = `category`.`cat`
LEFT OUTER JOIN `promo` ON `promo`.`ads_id` = `ads`.`id`
LEFT OUTER JOIN ads_rating ON `ads_rating`.`ad_id` = `ads`.`id`
WHERE `recycle_bin` != 1 AND `hidden` =0 AND ( `promo`.`promotype` >0 OR `ads`.`user_id` = 20 OR `ads_rating`.`rating` >= 4 )
ORDER BY `promo_type` DESC, `updated` DESC
LIMIT 5000
不知道如何管理这条线:
LEFT OUTER JOIN ads_rating ON `ads_rating`.`ad_id` = `ads`.`id`
示例数据:
广告
ID |标题|身体|类别|等等
2 |漂亮的瞳孔|它的新| puppys |等
3 |丑陋的傀儡|它的老| puppys | etc
评级
ID | ad_id | USER_ID |评级| rated_date
1 | 2 | 568 | 5 | 2017年10月2日
1 | 2 | 570 | 4 | 2017年10月3日
1 | 2 | 594 | 5 | 2017-10-1
因此,所需的结果集必须是
ID |头|体|类别| AVG_RATING
2 |漂亮的瞳孔|它是新的| puppys | 4.6
3 |丑陋的傀儡|它的老| puppys | null
谢谢!
答案 0 :(得分:1)
您使用的LEFT [OUTER] JOIN语法似乎没问题,但我们无权访问任何样本数据来验证。但是,您的查询有一个方面可能会令人困惑,这是您在where子句AND ads_rating.rating >= 4
中引入的额外条件。
我认为您可能会发现在连接中包含额外条件而不是在where子句中更容易,例如:
select ...
FROM `ads`
JOIN `category` ON `category`.`id` = `ads`.`subcat_id`
JOIN `supercategory` ON `supercategory`.`id` = `category`.`cat`
LEFT OUTER JOIN `promo` ON `promo`.`ads_id` = `ads`.`id`
LEFT OUTER JOIN ads_rating ON `ads_rating`.`ad_id` = `ads`.`id`
AND `ads_rating`.`rating` >= 4
WHERE `recycle_bin` != 1
AND `hidden` =0
AND ( `promo`.`promotype` >0
OR `ads`.`user_id` = 20
)
ORDER BY `promo_type` DESC, `updated` DESC
LIMIT 5000
这样做的原因是LEFT JOIN将允许返回ads
表中的一行,即使没有相应的ads_rating
信息,因此来自ads_rating
的任何列都将发生这种情况时为NULL。 e.g。
ads.id ads_rating.rating
1 4
2 NULL
如果你的where子句包含AND ads_rating.rating >= 4
,则id 2将被排除在最终结果之外,因此该谓词有效地使LEFT JOIN成为INNER JOIN的等价物。
因此。当使用任何OUTER连接(例如LEFT OUTER JOIN)时,要非常谨慎地引用where子句中的那些表。通常,将这些额外条件放入连接中会更简单。
答案 1 :(得分:1)
因此,如果您直接将广告加入此表格,您将获得针对特定广告的每个评分的行。因此,如果您只想获得平均评分而不是每个评分,那么您需要将ads_rating.rating更改为AVG(ads_rating.rating)并将其他所有内容分组。这会为您提供每个广告的平均评分。
SELECT
category.id AS category_id,
category.subcat AS category_name,
category.desc AS category_desc,
category.name AS category_pretty_name,
ads.id,
ads.header,
ads.price,
ads.oldprice,
ads.sellfast,
ads.hash,
ads.foto1,
ads.foto2,
ads.foto3,
ads.foto4,
ads.foto5,
ads.user_id,
SUBSTR(ads.body, 1, 160) AS body,
ads.subcat_id,
ads.updated,
ads.created,
ads.email,
ads.name,
ads.phone,
ads.hits,
ads.hidden,
promo.promotype AS promo_type,
supercategory.name AS supercategory_name,
supercategory.id AS supercategory_id,
**AVG(ads_rating.rating) as rating_average,**
promo.ads_id
FROM ads
inner join category ON category.id = ads.subcat_id
inner join supercategory ON supercategory.id = category.cat
LEFT OUTER JOIN promo ON promo.ads_id = ads.id
LEFT OUTER JOIN ads_rating ON ads_rating.ad_id = ads.id
WHERE recycle_bin != 1 AND hidden = 0 AND ( promo.promotype > 0 OR ads.user_id = 20 OR ads_rating.rating >= 4 )
GROUP BY
category.id AS category_id,
category.subcat AS category_name,
category.desc AS category_desc,
category.name AS category_pretty_name,
ads.id,
ads.header,
ads.price,
ads.oldprice,
ads.sellfast,
ads.hash,
ads.foto1,
ads.foto2,
ads.foto3,
ads.foto4,
ads.foto5,
ads.user_id,
SUBSTR(ads.body, 1, 160) AS body,
ads.subcat_id,
ads.updated,
ads.created,
ads.email,
ads.name,
ads.phone,
ads.hits,
ads.hidden,
promo.promotype AS promo_type,
supercategory.name AS supercategory_name,
supercategory.id AS supercategory_id
ORDER BY promo_type DESC, updated DESC
LIMIT 5000
另一种选择是实际加入两个单独的查询...见下文。实际上你正在做的是接受2个查询并加入它们就好像它们是表格一样。第二个不太理想,但如果您要汇总来自不同来源的不同数据,则可能非常有用,例如,如果您从促销和评级中提取平均值,并且需要在1个查询的结果中显示它们。
select q1.*, q2.average_rating
from
(
SELECT
category.id AS category_id,
category.subcat AS category_name,
category.desc AS category_desc,
category.name AS category_pretty_name,
ads.id as ads_id,
ads.header,
ads.price,
ads.oldprice,
ads.sellfast,
ads.hash,
ads.foto1,
ads.foto2,
ads.foto3,
ads.foto4,
ads.foto5,
ads.user_id,
SUBSTR(ads.body, 1, 160) AS body,
ads.subcat_id,
ads.updated,
ads.created,
ads.email,
ads.name,
ads.phone,
ads.hits,
ads.hidden,
promo.promotype AS promo_type,
supercategory.name AS supercategory_name,
supercategory.id AS supercategory_id
FROM ads
inner join category ON category.id = ads.subcat_id
inner join supercategory ON supercategory.id = category.cat
LEFT OUTER JOIN promo ON promo.ads_id = ads.id
LEFT OUTER JOIN ads_rating ON ads_rating.ad_id = ads.id
WHERE recycle_bin != 1 AND hidden = 0 AND ( promo.promotype > 0 OR ads.user_id = 20 OR ads_rating.rating >= 4 )
) q1
LEFT OUTER JOIN
(
select ads_id, avg(rating) as average_rating from ads_rating
group by ads_id
) q2
on q1.ads_id = q2.ads_id
ORDER BY promo_type DESC, updated DESC
LIMIT 5000
希望这会有所帮助。如果有任何错别字,我道歉。我在记事本中这样做了。解决任何错误,我会向您发送修复
答案 2 :(得分:0)
到目前为止,这是我能找到的最佳解决方案,感谢@ beautiful.drifter
SELECT q1.*, q2.average_rating FROM (
SELECT category.id AS category_id,
category.subcat AS category_name,
category.desc AS category_desc,
category.name AS category_pretty_name,
ads.id as ads_id,
ads.header,
ads.price,
ads.oldprice,
ads.sellfast,
ads.hash,
ads.foto1,
ads.foto2,
ads.foto3,
ads.foto4,
ads.foto5,
ads.user_id,
SUBSTR(ads.body, 1, 160) AS body,
ads.subcat_id,
ads.updated,
ads.created,
ads.email,
ads.name,
ads.phone,
ads.hits,
ads.hidden,
ads.recycle_bin,
promo.promotype AS promo_type,
supercategory.name AS supercategory_name,
supercategory.id AS supercategory_id
FROM ads
INNER JOIN category ON category.id = ads.subcat_id
INNER JOIN supercategory ON supercategory.id = category.cat
LEFT OUTER JOIN promo ON promo.ads_id = ads.id
) q1
LEFT OUTER JOIN (
SELECT ad_id, avg(rating) as average_rating from ads_rating
group by ad_id
) q2
ON q1.ads_id = q2.ad_id
WHERE q1.recycle_bin != 1 AND q1.hidden = 0 AND ( q1.promo_type > 0 OR q2.average_rating >= 4 )
ORDER BY promo_type DESC, updated DESC