1

ManyToMany 関係を持つ 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 つのタグに同じ最高スコアの画像がある場合、重複する画像を避けるために 2 番目に高いスコアの画像を選択する必要があることです。

何か案は..?

4

2 に答える 2

0

画像ごとに、3 つのタグのどれが最適かを選択します。次に、その中から最適なものを選択します。

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 に答える
0

2位タイピックのアイデアについてはよくわかりませんが、最大期間が必要だと思いますか? これはテストされていませんが、うまくいくかもしれません。サブクエリを使用して、画像ごとの最大スコアを取得してください。

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 に答える