我有2个具有ManyToMany关系的表:
Image {id, name, score}
Tag {id, name}
Images_Tags {image_id, tag_id}
我想通过他们的ID(20,21,22)选择3个特定标签,并为每个标签选择用此标签标记的最高得分图像。
这就是我想出来的:
SELECT * FROM (
SELECT t.id AS tag_id, t.name AS tag_name, i.* FROM `acme_tag` t
LEFT JOIN `acme_images_tags` r ON t.id = r.tag_id
LEFT JOIN `acme_images` i ON i.id = r.image_id
WHERE t.id IN (20, 21, 22)
ORDER BY i.score DESC
) f
GROUP BY f.tag_id
棘手的部分我试图解决的问题是,当2个标签具有相同得分最高的图像时,它应该选择第二个得分最高的图像到避免重复图像。
任何想法......?
答案 0 :(得分:0)
不太确定你的领带选择第二名的想法,我想你想要最长时间吗? 这是未经测试但这可能有效,使用子查询来获得每个图像的最大分数。
SELECT t.id AS tag_id, t.name AS tag_name
FROM `acme_tag` t
LEFT JOIN `acme_images_tags` r ON t.id = r.tag_id
LEFT JOIN
(SELECT id, max(score) from image group by id) AS max_i
ON max_i.id = r.image_id
WHERE t.id IN (20, 21, 22)
答案 1 :(得分:0)
对于每张图片,请选择三个标签中哪一个最佳。然后选择其中最好的。
您可以在MySQL中使用以下技巧为每个图像选择最佳效果:
select i.id, max(score) as maxscore,
substring_index(group_concat(it.tag_id order by score desc, rand()), ',', 1) as prefTag
from image i join
acme_images_tags it
on i.id = it.image_id and
it.tag_id in (20, 21, 22)
group by i.id;
prefTag
的复杂表达式为每个图像选择得分最高的标记。 rand()
用来处理关系,以确保所有具有相同最佳得分的标签都有相同的机会。
然后,您可以使用相同的想法为每个标签选择最佳图像:
select prefTag,
substring_index(group_concat(id order by maxscore desc), ',', 1) as image_id
from (select i.id, max(score) as maxscore,
substring_index(group_concat(it.tag_id order by score desc, rand()), ',', 1) as prefTag
from image i join
acme_images_tags it
on i.id = it.image_id and
it.tag_id in (20, 21, 22)
group by i.id
) t
group by prefTag
这比我之前使用union all
的解决方案更简单(但等效)。我要离开下面了。
(select i.id, max(score) as maxscore,
substring_index(group_concat(it.tag_id order by score desc), ',', 1) as prefTag
from image i join
acme_images_tags it
on i.id = it.image_id and
it.tag_id in (20, 21, 22)
group by i.id
having preftag = 20
order by maxscore desc
limit 1
) union all
(select i.id, max(score) as maxscore,
substring_index(group_concat(it.tag_id order by score desc), ',', 1) as prefTag
from image i join
acme_images_tags it
on i.id = it.image_id and
it.tag_id in (20, 21, 22)
group by i.id
having preftag = 21
order by maxscore desc
limit 1
) union all
(select i.id, max(score) as maxscore,
substring_index(group_concat(it.tag_id order by score desc), ',', 1) as prefTag
from image i join
acme_images_tags it
on i.id = it.image_id and
it.tag_id in (20, 21, 22)
group by i.id
having preftag = 22
order by maxscore desc
limit 1
)