在包含 As 和 B 的表中,选择 B 全部与给定 B_criteria 列表关联的那些 As

问题描述 投票:0回答:1

给出以下表结构:

表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
  • 数据库:Oracle
sql oracle performance query-optimization
1个回答
0
投票

您可以按照您的说明使用以下内容来满足您的要求

 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;
© www.soinside.com 2019 - 2024. All rights reserved.