独特的ManyToMany选择

时间:2013-06-18 10:45:01

标签: mysql join many-to-many unique

我有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个标签具有相同得分最高的图像时,它应该选择第二个得分最高的图像到避免重复图像。

任何想法......?

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
)
相关问题