我目前正在运行一些使用IN表达式匹配多个ID的SQL。但是,我希望能够将某些ID与其他ID匹配,以便它们必须一起显示才能返回结果。这是一个例子:
编辑:我匹配的ID是多对多关系的一部分。结构是这样的:
文章 ArticleKeywords 关键字
文章可以通过ArticleKeywords表将多个关键字链接到它。我目前正在使用IN表达式来匹配记录中的任何关键字ID。但是,我想将某些记录与小组关键字匹配,即关键字必须与另一个关键字一起出现才能匹配记录。
电流: ... AND id IN('25','566','156','166','7345')
更具体: ...... AND((id = '25'AND id ='566')OR(id ='156'AND id ='166')OR(id ='7345'))
虽然第二种选择可能有用,但我认为它可能不会非常精通。有没有其他方法可以做到,或者我应该采取另一种方式?
感谢您的帮助。
答案 0 :(得分:3)
根据评论进行编辑。假设您正在搜索以下文章:
您可以查询:
select a.id
from Articles a
inner join ArticleKeywords ak on ak.articleid = a.id
inner join Keywords k on k.id = ak.keywordid
group by a.id
having
sum(case when k.name in ('a1') then 1 else 0 end) = 1
or sum(case when k.name in ('b1','b2') then 1 else 0 end) = 2
or sum(case when k.name in ('c1','c2,'c3') then 1 else 0 end) > 0
根据SquareCog的评论,您可以使用早期的WHERE子句大大提高性能。该条款仅将分组限制为相关关键字。在上面的查询中,在HAVING:
之前添加WHERE...
inner join Keywords k on k.id = ak.keywordid
where k.name in ('a1','b1','b2','c1','c2','c3')
group by a.id
...
您可以检索文章的其他详细信息,如:
select *
from Articles
where id in (
...query from above here...
)
假设您有一个包含要搜索的组的表,定义如下:
groupid - keywordid
1 - 1
1 - 2
2 - 3
意味着文章必须匹配((关键字1和关键字2)或关键字3)。然后你可以像这样查询:
select ak.articleid
from ArticleKeywords ak
inner join Search s on ak.keywordid = s.keywordid
group by s.searchgroup, ak.articleid
having count(*) = (
select count(*) from #Search s2 where s2.Searchgroup = s.SearchGroup
)
答案 1 :(得分:2)
那么你的第二个选择永远不会有用......
((id = '25' AND id = '566') --For this to return the column `id` would have to = both 25 & 566 which it obviously can't
OR
(id = '156' AND id = '166') --For this to return the column `id` would have to = both 156 & 166 which it obviously can't
OR
(id = '7345'))
你到底想要实现什么......你的意思是“将某些ID与其他人匹配,以便他们必须一起出现”你的意思是连续的行吗?
答案 2 :(得分:1)
Andomar使用GROUP BY
和HAVING
提供的answer是解决此类问题的常用方法,但效果不佳。 GROUP BY
经常导致临时表。
回到你的例子:
... AND((id = '25'AND id ='566')OR(id ='156'AND id ='166')OR(id ='7345'))
这永远不会成真。 WHERE
子句中的条件一次适用于一个行。 id
列在给定行上永远不会有两个值。我从概念上理解你打算测试什么,但这不是SQL的工作方式。
当您需要编写涉及多行中出现的值的条件时,另一种解决方案是使用自联接。
SELECT *
FROM ArticleKeywords k1
LEFT OUTER JOIN ArticleKeywords k2 ON (k1.article_id = k2.article_id)
WHERE k1.keyword_id = '7345'
OR (k1.keyword_id = '25' AND k2.keyword_id = '566')
OR (k1.keyword_id = '156' AND k2.keyword_id = '166');
大多数人会将k1
和k2
称为“表别名”。但是,如果您将这些别名视为指向表中的各个行,那么使用自连接编写条件就会变得更加清晰。
当然,如果你需要测试一组三个值而不是两个值,你需要做另一个自我连接。
此解决方案可能无法有效地使用索引,但它不会产生GROUP BY
解决方案所执行的临时表。尝试两种解决方案,使用EXPLAIN
进行分析,然后测量其性能以进行比较。