Mysql 为标记匹配优化SQL查询
示例数据集:Mysql 为标记匹配优化SQL查询,mysql,sql,optimization,query-optimization,sql-optimization,Mysql,Sql,Optimization,Query Optimization,Sql Optimization,示例数据集: id | tag ---|------ 1 | car 1 | bike 2 | boat 2 | bike 3 | plane 3 | car id和tag都编制了索引 我正在尝试获取与标签[汽车、自行车]匹配的id(标签的数量可能会有所不同) 这样做的简单查询是: SELECT id FROM test WHERE tag = 'car' OR tag = 'bike' GROUP BY id HAVING COUNT(*) = 2 然而,这样做是非常
id | tag
---|------
1 | car
1 | bike
2 | boat
2 | bike
3 | plane
3 | car
id
和tag
都编制了索引
我正在尝试获取与标签[汽车、自行车]匹配的id(标签的数量可能会有所不同)
这样做的简单查询是:
SELECT id
FROM test
WHERE tag = 'car'
OR tag = 'bike'
GROUP BY id
HAVING COUNT(*) = 2
然而,这样做是非常低效的,因为group by,并且group by考虑了匹配一个标记的任何行(我有一个大容量)
对于这种情况是否有更有效的查询
我看到的唯一解决方案是另一个包含以下内容的表:
id | hash
---|------
1 | car,bike
2 | boat,bike
3 | plane,car
但这并不是一个易于实现和保持最新的解决方案
其他信息:
- 名称匹配必须精确(无全文索引)
- 标记的数量并不总是2
SELECT id
FROM test
WHERE tag in('car','bike')
GROUP BY id
HAVING COUNT(*) = 2
select tag, count(*) as amount
into #temp
from MYTABLE
group by tag
select t1.tag
from #temp t1 join #temp t2 on t1.amount=t2.amount and t1.tag=t2.tag and t1.amount=2
并在标记列上创建一个非聚集索引不确定我是否能找到您,但请尝试以下操作:
select tag, count(*) as amount
into #temp
from MYTABLE
group by tag
select t1.tag
from #temp t1 join #temp t2 on t1.amount=t2.amount and t1.tag=t2.tag and t1.amount=2
应该是自行车和汽车,因为它们都有2行,而HC等于2
select id from TEST where tag = 'car' and ID in (select id from TEST where tag='bike')
很好地表达了你的问题。举个例子,这将是完美的:)我将从规范化标记开始。您应该有一个带有ID和名称的标记表。那么您上面的数据集将是id,TagIDso在这种情况下,结果将是car和bike,因为它们都有两行名称?您的问题放错地方了。您的“天真”查询很好。(tag,id)上的索引应该为这个查询提供非常好的性能,因为只有使用索引才能满足要求。@Tobsey实际上它们都是id,但我想尽可能简化这个问题,并使它能够快速理解。中的
是或
的同义词。这没有什么区别。实际上IN的速度比ORI在
中没有想到的要快。事实上,你们中有人有支持这两种可能性的链接吗(快还是不快)?检查此链接:。在这里阅读所有答案,我还建议在in子句中有大量参数的情况下使用temp table。但在这里,我认为您不会有大量的标记。在OP中:“标记的数量并不总是2”是的,但您可以使用更多的“ID in”扩展查询。您已经需要在查询中进行某种“知道要搜索多少内容”。在这个例子中,你可以使用干净的索引,不需要任何分组和计数。可以否决它,但请对照答案中的其他例子分析查询。你会发现这要快得多。不管你怎么做,你仍然需要“构建”查询,查询中有多少“标签”(汽车、自行车等)。我正在尝试优化查询,你的方式似乎没有更有效?我认为值得尝试一下,比较一下计划。