我如何有效地查询数据库中与基于联接 table 的筛选器相匹配的所有行?
How can I efficiently query for all rows in a database matching a filter based on a joined table?
如果问题标题不清楚,我们深表歉意;如果没有更多细节,我不确定如何表达这一点。
我有一个 table foos
像:
id (bigint) | details (json)
1 | {someKey: 'someValue' ...}
2 | {someKey: 'otherValue' ...}
...
我也有一个tablefoo_labels
喜欢:
foo_id (bigint) | label_id (bigint)
1 | 10
2 | 13
...
我有兴趣检索所有与特定标签过滤器匹配的 foo。例如,如果我想获取所有标签为 5 或 6 的 foo,我可以这样做:
select f.* from foos f
join foo_labels fl on f.id = fl.foo_id
where fl.label_id in (5, 6)
group by f.id
同样,我可以使用类似以下内容获取所有带有标签 5 和 6 的 foos:
select f.* from foos f
join foo_labels fl on f.id = fl.foo_id
where fl.label_id in (5, 6)
group by f.id
having count(fl.label_id) = 2;
但我遇到了更复杂的查询。例如,我将如何进行查询以获取所有具有(标签 1 或标签 2)和(标签 3 或标签 4)的 foos。更抽象地说,我想执行一个查询来获取所有具有与一组 OR 子句匹配的标签的 foo,并将它们组合在一起,例如:
(l_{11} OR l_{12} OR ...) AND (l_{21} OR l_{22} OR ...) AND ...
我试过使用它,但找不到只涉及 foo_labels
table 中的一个 join
的解决方案;现在我能让它工作的唯一方法是每个 OR 子句执行一个 join
。有没有办法在只加入 foo_labels
table 一次的情况下进行这样的查询?我正在使用 MySql,但如果您知道如何在 SQL 的类似版本中执行此操作,那也可能有帮助吗?
how would I do a query to get all the foos that have (label 1 OR label 2) AND (label 3 OR label 4)?
您可以在 having
子句中包含条件表达式,例如:
select f.*
from foos f
join foo_labels fl on f.id = fl.foo_id
where fl.label_id in (1, 2, 3, 4)
group by f.id
having
max(fl.label_id in (1, 2)) = 1
and max(fl.label_id in (3, 4)) = 1
;
where
子句不是绝对必要的,但它通过限制聚合前的行数来提高查询效率。
(label 1 OR label 2) AND (label 3 OR label 4)
一般来说,您可以在没有 where
的 having
子句中执行此操作。 join
到 foo
对查询没有任何帮助。这是想法:
select fl.foo_id
from foo_labels fl
group by fl.foo_id
having sum( label_id in (1, 2) ) > 0 and
sum( label_id in (3, 4) ) > 0 ;
这很容易扩展到更复杂的组合。
如果问题标题不清楚,我们深表歉意;如果没有更多细节,我不确定如何表达这一点。
我有一个 table foos
像:
id (bigint) | details (json)
1 | {someKey: 'someValue' ...}
2 | {someKey: 'otherValue' ...}
...
我也有一个tablefoo_labels
喜欢:
foo_id (bigint) | label_id (bigint)
1 | 10
2 | 13
...
我有兴趣检索所有与特定标签过滤器匹配的 foo。例如,如果我想获取所有标签为 5 或 6 的 foo,我可以这样做:
select f.* from foos f
join foo_labels fl on f.id = fl.foo_id
where fl.label_id in (5, 6)
group by f.id
同样,我可以使用类似以下内容获取所有带有标签 5 和 6 的 foos:
select f.* from foos f
join foo_labels fl on f.id = fl.foo_id
where fl.label_id in (5, 6)
group by f.id
having count(fl.label_id) = 2;
但我遇到了更复杂的查询。例如,我将如何进行查询以获取所有具有(标签 1 或标签 2)和(标签 3 或标签 4)的 foos。更抽象地说,我想执行一个查询来获取所有具有与一组 OR 子句匹配的标签的 foo,并将它们组合在一起,例如:
(l_{11} OR l_{12} OR ...) AND (l_{21} OR l_{22} OR ...) AND ...
我试过使用它,但找不到只涉及 foo_labels
table 中的一个 join
的解决方案;现在我能让它工作的唯一方法是每个 OR 子句执行一个 join
。有没有办法在只加入 foo_labels
table 一次的情况下进行这样的查询?我正在使用 MySql,但如果您知道如何在 SQL 的类似版本中执行此操作,那也可能有帮助吗?
how would I do a query to get all the foos that have (label 1 OR label 2) AND (label 3 OR label 4)?
您可以在 having
子句中包含条件表达式,例如:
select f.*
from foos f
join foo_labels fl on f.id = fl.foo_id
where fl.label_id in (1, 2, 3, 4)
group by f.id
having
max(fl.label_id in (1, 2)) = 1
and max(fl.label_id in (3, 4)) = 1
;
where
子句不是绝对必要的,但它通过限制聚合前的行数来提高查询效率。
(label 1 OR label 2) AND (label 3 OR label 4)
一般来说,您可以在没有 where
的 having
子句中执行此操作。 join
到 foo
对查询没有任何帮助。这是想法:
select fl.foo_id
from foo_labels fl
group by fl.foo_id
having sum( label_id in (1, 2) ) > 0 and
sum( label_id in (3, 4) ) > 0 ;
这很容易扩展到更复杂的组合。