给出以下表结构:
表A
a |
---|
1 |
2 |
3 |
表AB
a | b |
---|---|
1 | 1 |
1 | 2 |
1 | 3 |
2 | 1 |
2 | 2 |
3 | 2 |
3 | 3 |
表B
b |
---|
1 |
2 |
3 |
问题描述:给定一个
b
列表,我想查询那些与a
中所有b
相关的AB
。
或更笼统地说,我想检索与给定条件列表
a
匹配的所有 b
。 b
列表的长度(即标准计数)可以是 1 到 20 之间的任意值。
示例:给定
b
的 (2, 3)
列表,我想检索 a
的 1 和 3,因为它们分别与 AB
中的 2 和 3 相关联。
问题:所描述的问题听起来像是一个经常出现的非常普遍的问题 - 是否有关于如何在关系数据库中有效解决此查询模式的最佳解决方案?
有没有更优化的方式来设置表结构来回答这个特定的查询模式?这里使用的最佳索引类型是什么?
我目前的做法
目前我使用以下方法,但是我不确定这是否是最有效地选择数据的最佳方法。
我在
A(a)
、B(b)
、AB(a,b)
、AB(b,a)
上使用 B 树索引。
我们称之为条件列表
b_criteria=(b1, b2, ...)
,我用以下方式查询数据:
SELECT DISTINCT ab.a
FROM AB ab
WHERE
ab.b = `b_criteria[b_lowest_cardinality_index]`
AND EXISTS (SELECT 1 FROM AB q WHERE ab.a = q.a AND q.b = `b_criteria[1]`)
AND EXISTS (SELECT 1 FROM AB q WHERE ab.a = q.a AND q.b = `b_criteria[2]`)
...
AND EXISTS (SELECT 1 FROM AB q WHERE ab.a = q.a AND q.b = `b_criteria[n]`)
所以我选择
a
都与 EXISTS
子句匹配。
此外,我尝试通过仅预选带有
b=b_lowest_cardinality
的行来从尽可能少的行数开始。我可以通过计算 b_lowest_cardinality
中总共有多少个由 count(b)
分组的 b
来预先选择 AB
。 b
的基数在 AB
中差异很大(例如,b=3
中可能有更多的 AB
,如 b=2
)。
背景信息:
以我为例
A
行数:4亿AB
行数:40亿B
行数:4000您可以按照您的说明使用以下内容来满足您的要求
with data as (select
1 a, 1 b from dual union all
select 1, 2 from dual union all
select 1, 3 from dual union all
select 2, 1 from dual union all
select 2, 2 from dual union all
select 3, 2 from dual union all
select 3, 3 from dual)
select A,B from (select sum(1) over (partition by A ) sum1 ,a,b ,sum(1) over (partition by a) count1,count(distinct b) over () count2
from data
where b in (2,3)
)
where sum1=count1
and count1=count2
order by A,B;