我有一个名为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列,包括审计跟踪信息。我已将它们减少到这里以使问题集中。
答案 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)
)
)