1

我有 2 个具有多对多关系的表:

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

有任何想法吗..?

4

2 回答 2

0

Not so sure about your if tie pick second place idea, I think you want the max period right? This is untested but this might work, use a subquery to get the max score per image.

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)
于 2013-06-18T11:12:36.227 回答
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
)
于 2013-06-18T11:19:29.353 回答