SQL如何根据选择标准确定自连接的计数和顺序

时间:2017-10-13 22:57:43

标签: sql algorithm

我有一个名为ATTR的键值表,其中数据与单个逻辑记录相关(已识别 通过S#)存储为键值对。

table ATTR:
S#   KEY    VALUE

所以,给出psuedo-code中的标准:

Select S# Where k1 > 5

变为

Select t1.S# 
from ATTR t1 
where t1.KEY = 'k1' AND t1.VALUE > 5

等等。实际上我的所有用例都涉及一个或多个自联接。

我的问题是 - 根据标准,是否有科学的方法 推导出所需的自连接数量,以及如何实现。它需要吗? 重新安排标准(我想避免这样的重新安排 - 让... dbms查询优化器负责处理)。

举一些说明性的例子

crit: where k1 > 5 OR k2 > 10
=> no extra join needed
Select t1.S# 
from ATTR t1 
where (t1.KEY = 'k1' AND t1.VALUE > 5) OR (t1.KEY = 'k2' AND t1.VALUE > 10)

crit: where k1 > 5 AND k2 > 10
=> 1 self-join needed
Select t1.S# 
from ATTR t1 
inner join ATTR t2 on t1.S# = t2.S#
where (t1.KEY = 'k1' AND t1.VALUE > 5)
        AND
      (t2.KEY = 'k2' AND t2.VALUE > 10)

crit: where k1 > 5 AND k2 > 10 AND k3 > 20
=> 2 self-joins needed
Select t1.S# 
from ATTR t1 
inner join ATTR t2 on t1.S# = t2.S#
inner join ATTR t3 on t1.S# = t3.S#
where (t1.KEY = 'k1' AND t1.VALUE > 5)
        AND
      (t2.KEY = 'k2' AND t2.VALUE > 10)
        AND
      (t3.KEY = 'k3' AND t3.VALUE > 20)

crit: where (k1 > 5 OR k2 > 10) AND (k1 > 10 OR  K3 > 20)
=> 1 self-join needed
Select t1.S# 
from ATTR t1 
inner join ATTR t2 on t1.S# = t2.S#
where ( (t1.KEY = 'k1' AND t1.VALUE > 5) OR (t1.KEY = 'k2' AND t1.VALUE > 10) )
        AND
      ( (t1.KEY = 'k1' AND t1.VALUE > 10) OR (t2.KEY = 'k3' AND t2.VALUE > 20) )

crit: where (k1 > 5 AND k2 > 10) or (k1 > 10 OR K3 > k4)
and so on
=> ??

我对原子表达式的数量(即最小的布尔表达式)没有设置限制,除了它们被组合 仅使用AND OR NOT。但是如果允许一些很酷的算法,我可以愉快地设定一个限制(例如10-20个原子)。我相信所有RDBMS也都有一些基本的限制。我也在想XOR案例可以折叠成AND,而NOT不是问题的原因。

我正在使用一个列数据库。

非常感谢

编辑#2 - 添加了一些示例数据

S#  KEY VALUE
1   k1  1
1   k2  5
1   k3  10
1   k4  20
2   k1  10
2   k2  20
2   k3  30
2   k4  40
2   k5  50
3   k2  11
3   k4  22
3   k6  33
3   k8  44
3   k10 55
and so  on

在大约500万行中,总共有大约900个不同的键。大多数“记录”使用大约50-60个不同的密钥。实际表中包含大约20列,包括审计跟踪信息。我已将它们减少到这里以使问题集中。

1 个答案:

答案 0 :(得分:0)

通常,具有Key = 'k1' AND Value > 5操作数的每个键值标准(例如AND)都需要单独的表查找。 一旦你弄清楚如何解析你的标准(例如,其中k1> 5和k2> 10 ),你将能够生成所需的SQL代码。

您不必明确使用JOIN关键字。您可以改为使用EXISTS,这可能更容易阅读。以下是基于您提供的标准的示例:

where (k1 > 5 OR k2 > 10) AND (k1 > 10 OR K3 > 20)
SELECT t.s#
FROM ATTR t
WHERE 1=1
-- KVP on left side of the AND
AND EXISTS (
    SELECT 1
    FROM ATTR t1
    WHERE t.S# = t1.S# -- Join sub-query to parent query
    AND (
        (t1.Key = 'k1' AND t1.Value > 5)
        OR
        (t1.Key = 'k2' AND t1.Value > 10)
        )
)
-- KVP on right side of the AND
AND EXISTS (
    SELECT 1
    FROM ATTR t1
    WHERE t.S# = t1.S# -- Join sub-query to parent query
    AND (
        (t1.Key = 'k1' AND t1.Value > 10)
        OR
        (t1.Key = 'k3' AND t1.Value > 20)
        )
)