我有三张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")
...这意味着我想找到所有带有肮脏道路的图片,两点透视,并且有侧面或前面的光线。
我该怎么办?感谢。
答案 0 :(得分:3)
我认为你必须将标签表加入照片表四次......非常难看。
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'
)
答案 1 :(得分:1)
道歉,我没有意识到你使用的是MySQL - 更新后的答案。
假设每张照片只能为每张照片指定一次(即照片不能多次标记为“脏”):
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
答案 2 :(得分: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