我有以下表格:
CREATE TABLE `content` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`content` varchar(255) NOT NULL,
`tag_a_id` int unsigned DEFAULT NULL,
`tag_b_id` int unsigned DEFAULT NULL,
`tag_c_id` int unsigned DEFAULT NULL,
`tag_d_id` int unsigned DEFAULT NULL,
`tag_e_id` int unsigned DEFAULT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `tags` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`tag` varchar(32) NOT NULL UNIQUE,
PRIMARY KEY (`id`)
);
tags
表与内容表具有一对多关系,使用tag_?_id
字段,但每个标记ID每行仅显示ONCE。
我想进行一个查询,在其中我从content
表中选择与给定标记集(以及所有关联的标记)相关联的所有行。例如,“获取所有标记为”News“和”MedicalCare“的内容行。
这意味着需要在tags
表中查找“News”和“MedicalCare”的ID,然后使用一对查询将其注入content
表中的查询中这(假设这些标签具有ID 45
和68
):
SELECT id FROM tags WHERE tag IN ("News","MedicalCare");
......然后......
SELECT t1.id, t1.content, ts_a.tag, ts_b.tag, ts_c.tag, ts_d.tag, ts_e.tag
FROM (
SELECT t.id, t.content, t.tag_a_id, t.tag_b_id, t.tag_c_id, t.tag_d_id, t.tag_e_id
FROM content t
WHERE 45 IN (t.tag_a_id, t.tag_b_id, t.tag_c_id, t.tag_d_id, t.tag_e_id)
AND 68 IN (t.tag_a_id, t.tag_b_id, t.tag_c_id, t.tag_d_id, t.tag_e_id)
ORDER BY t.id ASC LIMIT 200
) t1
LEFT JOIN tags ts_a ON t1.tag_a_id=ts_a.id
LEFT JOIN tags ts_b ON t1.tag_b_id=ts_b.id
LEFT JOIN tags ts_c ON t1.tag_c_id=ts_c.id
LEFT JOIN tags ts_d ON t1.tag_d_id=ts_d.id
LEFT JOIN tags ts_e ON t1.tag_e_id=ts_e.id;
有没有办法可以在这个查询中获取我对感兴趣的标记ID,并动态生成那些AND x IN(a,b,c)子句?
另一种选择可能是:
WHERE EVERY ONE OF (
SELECT id FROM tags WHERE tag IN ("News","MedicalCare")
) IN (t.tag_a_id, t.tag_b_id, t.tag_c_id, t.tag_d_id, t.tag_e_id)
请注意:content
表非常大,因此将内容表连接到标记表是不可行的,而不先过滤掉不需要的行并应用LIMIT
。
答案 0 :(得分:1)
如果您知道标签是唯一的,您可以执行以下操作:
where ((ts_a.tag in ('News', 'MecialCare')) +
(ts_b.tag in ('News', 'MecialCare')) +
(ts_c.tag in ('News', 'MecialCare')) +
(ts_d.tag in ('News', 'MecialCare')) +
(ts_e.tag in ('News', 'MecialCare'))
) = 2
这使用的事实是,在MySQL中,比较返回0或1,然后可以将它们加在一起。
顺便说一下,这个问题是为什么数据应该正确结构化的一个很好的理由,每个人的每个标签都有一个单独的行,一个persno_tag表。
答案 1 :(得分:1)
我认为这样做会:
select t1.id, t1.content, ts_a.tag, ts_b.tag, ts_c.tag, ts_d.tag, ts_e.tag
from content t1
LEFT JOIN tags ts_a ON t1.tag_a_id=ts_a.id
LEFT JOIN tags ts_b ON t1.tag_b_id=ts_b.id
LEFT JOIN tags ts_c ON t1.tag_c_id=ts_c.id
LEFT JOIN tags ts_d ON t1.tag_d_id=ts_d.id
LEFT JOIN tags ts_e ON t1.tag_e_id=ts_e.id
where "News" in (ts_a.tag, ts_b.tag, ts_c.tag, ts_d.tag, ts_e.tag)
and "MedicalCare" in (ts_a.tag, ts_b.tag, ts_c.tag, ts_d.tag, ts_e.tag)