[英]PHP MYSQL query, searching multiple fields/columns using data from multiple tables
很长一段时间潜伏在这里,多年来一直在使用这个网站的建议,现在我有一个问题,我找不到答案 - 我确信解决方案很简单!
我正在为音乐曲目建立一个标记系统。 我有三张桌子
曲目
---------------
| id | name |
---------------
| 1 | Track1 |
| 2 | Track2 |
---------------
Taglinks
--------------------------
| id | tag_id | track_id |
--------------------------
| 1 | 1 | 1 |
| 2 | 2 | 1 |
| 3 | 2 | 2 |
--------------------------
标签
-------------------------
| id | tag | type |
-------------------------
| 1 | acoustic | genre |
| 2 | anger | mood |
-------------------------
我希望能够获得曲目的曲目名称,例如,标签:声音,类型:流派和标签:愤怒,类型:心情。 所以在这种情况下我想要跟踪1,因为它有两个标签。
我当前的查询是
SELECT tracks.name
FROM tracks
JOIN taglinks ON tracks.id=taglinks.track_id
JOIN tags ON (tags.type='genre' AND tags.tag='acoustic') AND (tags.type='mood' AND tags.tag='anger')
WHERE taglinks.tag_id=tags.id;
如果我删除第二个JOIN中的AND部分,那么我将返回任何内容,然后我将所有轨道标记为预期的声音,如果我将其更改为OR,我将再次按预期获得两个轨道。
我如何做一个AND虽然只返回那些同时具有这些标签和类型的曲目?
提前致谢
编辑:
只是为了澄清我的追求。 我希望能够检索同时具有Acoustic和Anger作为标签的轨道,但仅当这些标签也与给定类型匹配时才能检索。
这是因为后来我可能会有一个名为jazz的类型为genre的标签,以及一个名为jazz的带有类型样式的标签,我需要能够确保选择正确的标签类型以及标签本身。
这是我正在使用的sqlfiddle的链接 - http://sqlfiddle.com/#!2/aad82/3 。
到目前为止,吉尔斯的答案似乎是一个很好的解决方案!
这应该没问题
select
t.name
from
tracks as t
inner join taglinks as tl on t.id = tl.track_id
inner join tags as tg on tl.tag_id = tg.id
where
tg.tag = 'acoustic' and
tg.type = 'genre' and
tg.tag = 'anger' and
tg.type = 'mood';
注意:我使用as identifier
name as identifier
,因为它可以节省在任何地方写表名。 你不必。
编辑
我可能会误解你的问题,所以这个也可能有所帮助:
select
t.name
from
tracks as t
inner join taglinks as tl on t.id = tl.track_id
inner join tags as tg on tl.tag_id = tg.id
where
(tg.tag = 'acoustic' and
tg.type = 'genre') or
(tg.tag = 'anger' and
tg.type = 'mood');
这将返回具有正确类型AND标记的结果,但不必拥有所有这些结果。
问题是轨道应该有2个标签等于要求的值,所有发布的请求在那种情况下都不起作用。 必须使用INTERSECT sql命令,但这个命令在mysql中不可用。
这样的东西应该工作:
SELECT tracks.id, tracks.name
FROM `taglinks`
LEFT JOIN tags ON tags.id = taglinks.tag_id
LEFT JOIN tracks ON tracks.id = taglinks.track_id
WHERE (
tag = 'accoustic'
AND `type` = 'genre'
)
OR (
tag = 'anger'
AND `type`= 'mood'
)
GROUP BY track_id
HAVING COUNT( * ) =2
GROUP BY
匹配的tage数。 accoustic = 'genre'
和anger = 'mood'
并找到该行的2行,那么它匹配2个条件并保持最终结果 HAVING COUNT( * ) =2
SELECT * FROM tracks tracks
INNER JOIN
(SELECT taglinks.track_id, COUNT(*) as cnt
FROM tags tags
INNER JOIN taglinks taglinks ON taglinks.tag_id = tags.id
WHERE
(tags.tag='ac' AND tags.type='ge')
OR (tags.tag='an' AND tags.type='mo')
GROUP BY taglinks.track_id
)AS track_match
ON track_match.track_id = tracks.id AND track_match.cnt = 2
您需要替换“track_match.cnt = 2”2 =要匹配的条件数
此解决方案提供了一些灵活性:您还可以在满足最少条件的情况下使用轨道。
例如,您可以在此添加track_match.cnt> = 1以及ORDER BY track_match.cnt DESC
获取按匹配条件数排序的轨道列表。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.