6

写真、タグ、タグ写真の 3 つの MySQL テーブルと、写真とタグの m:n 関係があります。

Photos:     id | filename | ...
Tags:       id | name
Tagsphotos: photo | tag

この条件の写真をすべて選択したい:

(tagged as "dirty" AND tagged as "road") AND (tagged as "light.front" OR tagged as "light.side") AND (tagged as "perspective.two-point")

...つまり、道路が汚れていて、2 点透視図で、サイド ライトまたはフロント ライトを使用しているすべての写真を検索したいということです。

どうすればいいですか?ありがとう。

4

3 に答える 3

3

tags テーブルを photos テーブルに 4 回結合する必要があると思います...かなり醜いです。

SELECT Photos.*
FROM
  Photos
  JOIN (
    Tagsphotos JOIN Tags ON (Tags.id = Tagsphotos.tag)
  ) t1 ON (t1.photo = Photos.id)
  JOIN (
    Tagsphotos JOIN Tags ON (Tags.id = Tagsphotos.tag)
  ) t2 ON (t2.photo = Photos.id)
  JOIN (
    Tagsphotos JOIN Tags ON (Tags.id = Tagsphotos.tag)
  ) t3 ON (t3.photo = Photos.id)
  JOIN (
    Tagsphotos JOIN Tags ON (Tags.id = Tagsphotos.tag)
  ) t4 ON (t4.photo = Photos.id)
WHERE
      (t1.name = 'dirty' AND t2.name = 'road')
  AND (t3.name = 'light.front' OR t3.name = 'light.side')
  AND (t4.name = 'perspective.two-point')

サブクエリはおそらくより高速です。

SELECT *
FROM Photos
WHERE
  Photos.id IN (
    SELECT Tagspohotos.photo
    FROM Tagsphotos JOIN Tags ON (Tags.id = Tagsphotos.tag)
    WHERE Tags.name = 'dirty'
  )
  AND Photos.id IN (
    SELECT Tagspohotos.photo
    FROM Tagsphotos JOIN Tags ON (Tags.id = Tagsphotos.tag)
    WHERE Tags.name = 'road'
  )
  AND Photos.id IN (
    SELECT Tagspohotos.photo
    FROM Tagsphotos JOIN Tags ON (Tags.id = Tagsphotos.tag)
    WHERE Tags.name = 'light.front' OR Tags.name = 'light.side'
  )
  AND Photos.id IN (
    SELECT Tagspohotos.photo
    FROM Tagsphotos JOIN Tags ON (Tags.id = Tagsphotos.tag)
    WHERE Tags.name = 'perspective.two-point'
  )
于 2012-04-30T12:37:55.327 に答える
1

申し訳ありませんが、MySQLを使用していることに気づきませんでした-以下に示す更新された回答。

各タグを指定できるのは写真ごとに1回だけであると仮定します(つまり、写真に「ダーティ」として複数回タグを付けることはできません)。

SELECT      P.id,
            P.[filename]
FROM        Photos P
INNER JOIN  Tagsphotos TP ON TP.photo = P.id
INNER JOIN  Tags T ON TP.tag = T.id
INNER JOIN  (
        SELECT  'dirty' name,
                10 [weight]
        UNION
        SELECT  'road' name,
                10 [weight]
        UNION
        SELECT  'perspective.two-point' name,
                10 [weight]
        UNION
        SELECT  'light.front' name,
                1 [weight]
        UNION
        SELECT  'light.side' name,
                1 [weight]
) R ON T.name = R.name
GROUP BY    P.id,
            P.[filename]
HAVING  SUM(R.[weight]) >= 31
于 2012-04-30T12:42:00.983 に答える
0

写真とタグの列が ID であると仮定します。

select p.* from Photos p, Tags t, Tagsphotos tp
where p.id = tp.photo and t.id = tp.tag
and t.tagged in ("dirty", "road", "perspective.two-point", "light.front")
group by p.photo
having count(distinct t.tagged) = 4

UNION

select p.* from Photos p, Tags t, Tagsphotos tp
where p.id = tp.photo and t.id = tp.tag
and t.tagged in ("dirty", "road", "perspective.two-point", "light.side")
group by p.photo
having count(distinct t.tagged) = 4
于 2012-04-30T12:36:23.007 に答える